2

我需要创建一个 HTML5 画布来捕获一些输入。我想渲染一个线条图(白底黑线)并允许用户为这些部分着色。

然后我希望能够在最后检索这些数据以在服务器端处理它,以便以后可以再次呈现它。

我想将用于渲染图像的数据存储在数据库中,以便可以绘制任何图像。

我查看了 HTML5 和 canvas 标签。也在 Kinetic js 库中。我已经能够快速演示我需要什么。

http://jsfiddle.net/6qskx/

从我演示的内容来看,这种方法很难维护,也很难首先设置图像,因为每个部分都需要制定和绘制,以便可以将事件添加到其中。

我的问题是 - 有没有人有任何类似这样的经验或许多框架中的任何一个建议:

  • 哪个框架最好
  • 哪种方法最灵活和可维护。
4

5 回答 5

6

我遇到了使用 Kinectic Js 库加载和检索数据(画布状态)的类似情况。

现在我正在使用fabric js库。https://github.com/kangax/fabric.js/

它通过canvas.toJSON()方法保存对象的属性或状态,然后使用canvas.loadFromJSON()方法重新加载画布。

于 2012-01-29T08:05:31.690 回答
1

在某些浏览器尤其是移动浏览器上无法查看 svg,但 Raphael Js 图片可以。使用 Raphael,它是一个非常好的库,在 svg 中使用它们的原始路径绘制图像,在 Raphael 绘图函数中添加该数据,瞧,你的图像在画布中。我使用 flex 和 fxg 以及矢量图像,当您需要构建界面时,没有什么比 fxg 和 flash 更快了,但是这些天我们仅限于 html5 和讨厌的 javascript :) 就像我们回到 90 年代一样

于 2012-05-05T13:29:46.813 回答
1

我玩过它,这个例子非常基础,不适合生产。您可以在http://xisse.net/shapes.php查看示例并在http://xisse.net/shapes.zip 下载源代码 您将需要一个运行 php 的网络服务器和一个 mysql 数据库。.zip 文件中包含一个 sql 文件。只需在 shape.php 文件中编辑 db 连接即可。我还将发布以下代码:

形状.php

    <html>
<head>
    <?php
    //connect to db
    mysql_connect('localhost','user','password');
    mysql_select_db('shapes');
    ?>
    <style>
       canvas
        {
            border: 1px solid #9C9898;
        }
    </style>

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
    <script src="http://www.html5canvastutorials.com/libraries/kinetic-v3.1.0.js"></script>
    <script type="text/javascript" src="shapes.js"></script>
    <script type="text/javascript">


        $(document).ready(function () {
            var stage;
            var canvas;
            var context;
            var cursor;
            var item = [];
            var rectX;
            var rectY

            prepareCanvas();

            function prepareCanvas() {

                stage = new Kinetic.Stage("container", 578, 200);
                canvas = stage.getCanvas();

                rectX = canvas.width / 2 - 50;
                rectY = canvas.height / 2 - 25;

                cursor = setupCursor();

                setupColours();

                setupItem();

                $('input[name=type]').change(setupItem);
            }

            /* Functions */

            function setupCursor() {
                return new Kinetic.Shape(function () {
                    var context = this.getContext();
                    context.beginPath();
                    context.lineWidth = 1;
                    context.strokeStyle = "black";
                    context.fillStyle = cursor.color;
                    context.arc(0, 0, 10, 0, Math.PI * 2, true);

                    context.closePath();
                    context.fill();
                    context.stroke();
                });
            }

            function setupColours() {
                var cBlack = createColour(20, 20, 20, 'black');
                var cWhite = createColour(20, 50, 20, 'white');
                var cRed = createColour(20, 20, 50, 'red');
                var cBlue = createColour(20, 50, 50, 'blue');
            }

            function createColour(size, x, y, colour) {
                var rectangle = new Kinetic.Shape(function () {
                    var context = this.getContext();
                    context.beginPath();
                    context.lineWidth = 1;
                    context.strokeStyle = 'black';
                    context.fillStyle = colour;
                    context.moveTo(x, y);
                    context.lineTo(x, y + size);
                    context.lineTo(x + size, y + size);
                    context.lineTo(x + size, y);
                    context.closePath();
                    context.fill();
                    context.stroke();
                });

                rectangle.addEventListener("click", function () {

                    cursor.color = colour;

                    addCursor();
                });

                stage.add(rectangle);

                return rectangle;
            }

            function moveCursor() {
                var mousePos = stage.getMousePos();

                cursor.x = mousePos.x + 10;
                cursor.y = mousePos.y + 10;
                stage.draw();
            }

            function addCursor() {

                stage.add(cursor);
                moveCursor();
                stage.addEventListener("mousemove", moveCursor, false);
            }

            function setupItem() {

                if (item) {
                    if (item.length > 0) {
                        for (var n = 0; n < item.length; n++) {
                            stage.remove(item[n]);
                        }
                    }
                }

                /* set shape attributes */
                <?php
                    //get shape info
                    $qShapeDetails  =   "SELECT * FROM shapeDefinitions ORDER BY shapeID ASC";
                    $rShapeDetails  =   mysql_query($qShapeDetails) or die('mysql has thrown an error: \n' . mysql_error());
                    while($shape    =   mysql_fetch_assoc($rShapeDetails))
                {
                ?>
                var shape<?php echo $shape['shapeID']; ?> = new Kinetic.Shape(function () {
                    var context = this.getContext();
                    context.beginPath();
                    context.lineWidth = <?php echo $shape['lineWidth']; ?>;
                    context.strokeStyle = '<?php echo $shape['strokeColour']; ?>';
                    context.fillStyle = shape<?php echo $shape['shapeID']; ?>.color;
                    <?php
                        $qLines =   "SELECT * FROM linePos WHERE shapeID = '" . $shape['shapeID'] . "' ORDER BY lineID ASC";
                        $rLines =   mysql_query($qLines) or die('mysql has thrown an error: \n' . mysql_error());
                        while($line =   mysql_fetch_assoc($rLines))
                        {
                            if($line['lineID']  ==  1)
                            {
                    ?>
                                context.moveTo(<?php echo $line['posX']; ?>, <?php echo $line['posY']; ?>);
                    <?php
                            } else {
                    ?>  
                        context.lineTo(<?php echo $line['posX']; ?>, <?php echo $line['posY']; ?>);
                    <?php
                            }
                        }
                    ?>
                    context.closePath();
                    context.fill();
                    context.stroke();
                });

                shape<?php echo $shape['shapeID']; ?>.color = 'white';

                shape<?php echo $shape['shapeID']; ?>.addEventListener("click", function () {
                    shape<?php echo $shape['shapeID']; ?>.color = cursor.color;
                    stage.draw();
                });

                item.push(shape<?php echo $shape['shapeID']; ?>);
                <?php
                }
                ?>


                for (var n = 0; n < item.length; n++) {
                    stage.add(item[n]);
                }

                stage.draw();
            }
        });</script>
</head>
<body onmousedown="return false;">
    <div id="container" style="cursor:crosshair;">
    </div>
</body>
</html>

SQL

    SET FOREIGN_KEY_CHECKS=0;
    -- ----------------------------
    -- Table structure for `linepos`
    -- ----------------------------
    DROP TABLE IF EXISTS `linepos`;
    CREATE TABLE `linepos` (
      `lineID` int(11) NOT NULL AUTO_INCREMENT,
      `shapeID` int(11) DEFAULT NULL,
      `posX` float DEFAULT NULL,
      `posY` float DEFAULT NULL,
      PRIMARY KEY (`lineID`)
    ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1;

    -- ----------------------------
    -- Records of linepos
    -- ----------------------------
    INSERT INTO `linepos` VALUES ('1', '1', '100', '10');
    INSERT INTO `linepos` VALUES ('2', '1', '100', '30');
    INSERT INTO `linepos` VALUES ('3', '1', '200', '30');
    INSERT INTO `linepos` VALUES ('4', '1', '200', '10');
    INSERT INTO `linepos` VALUES ('5', '2', '100', '30');
    INSERT INTO `linepos` VALUES ('6', '2', '100', '60');
    INSERT INTO `linepos` VALUES ('7', '2', '200', '60');
    INSERT INTO `linepos` VALUES ('8', '2', '200', '30');
    INSERT INTO `linepos` VALUES ('9', '3', '200', '20');
    INSERT INTO `linepos` VALUES ('10', '3', '200', '60');
    INSERT INTO `linepos` VALUES ('11', '3', '400', '60');
    INSERT INTO `linepos` VALUES ('12', '3', '400', '20');

    -- ----------------------------
    -- Table structure for `shapedefinitions`
    -- ----------------------------
    DROP TABLE IF EXISTS `shapedefinitions`;
    CREATE TABLE `shapedefinitions` (
      `shapeID` int(11) NOT NULL AUTO_INCREMENT,
      `lineWidth` float DEFAULT NULL,
      `strokeColour` varchar(255) DEFAULT NULL,
      `backGroundColour` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`shapeID`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

    -- ----------------------------
    -- Records of shapedefinitions
    -- ----------------------------
    INSERT INTO `shapedefinitions` VALUES ('1', '2', '#000', '#FFF');
    INSERT INTO `shapedefinitions` VALUES ('2', '2', '#000', '#FFF');
    INSERT INTO `shapedefinitions` VALUES ('3', '2', '#000', '#FFF');

那应该让你上路:)

于 2012-01-27T09:25:33.840 回答
0

I'm surprised no-one's mentioned raphael yet, as it seems to be the de facto standard in javascript/canvas interaction (at least it is where I work).

It has a simple syntax (using SVG Path strings) for drawing/storing lines/polygons http://raphaeljs.com/reference.html#Paper.path, for colouring them http://raphaeljs.com/reference.html#Element.attr and for handling events http://raphaeljs.com/reference.html#Element.click. Given this it'd be possible to store your drawings as a comma separated list of SVG paths, and your colourings as a comma separated list of values (put in an array when the image is being viewed/coloured in) with each value corresponding to one of your paths'

The rapahel documentation is a bit daunting as the api recently grew considerably there isn't and not too much indication of where to look for what (even if you knew the old API pretty well), but the demos on the home page are very useful for getting to know the API.

于 2012-01-31T23:27:35.377 回答
0

我同意 wheresrhys。SVG 似乎是您想要的更好的方法。在现有的 SVG 库中,raphael 允许您做很多事情。

于 2012-02-01T03:05:53.327 回答