最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Html5 Complex shape and events - recommend an approach for maintainable and flexible code - Stack Overflow

programmeradmin2浏览0评论

I have a requirement to create a HTML5 canvas to capture some inputs. I would like to render an line drawing (black line on white) and allow the user to colour the sections in.

I then would like to be able to retrieve this data at the end to process it on the server side and so that it can be rendered again at a later date.

I would like to store the data for rendering the image in a database so that potentially any image can be drawn.

I have looked in to HTML5 and the canvas tag. Also in to the Kinetic js library. I have been able to make a quick demo of what i require.

/

From what i have demo'd this approach would be very hard to maintain and hard to setup the images in the firstplace as each section would need to worked out and drawn so that events could be added to them.

My question is - does anyone have any experience with anything like this or any of the many frameworks out there to suggest:

  • which framework would be best
  • which approach would be most flexible and manintainable.

I have a requirement to create a HTML5 canvas to capture some inputs. I would like to render an line drawing (black line on white) and allow the user to colour the sections in.

I then would like to be able to retrieve this data at the end to process it on the server side and so that it can be rendered again at a later date.

I would like to store the data for rendering the image in a database so that potentially any image can be drawn.

I have looked in to HTML5 and the canvas tag. Also in to the Kinetic js library. I have been able to make a quick demo of what i require.

http://jsfiddle/6qskx/

From what i have demo'd this approach would be very hard to maintain and hard to setup the images in the firstplace as each section would need to worked out and drawn so that events could be added to them.

My question is - does anyone have any experience with anything like this or any of the many frameworks out there to suggest:

  • which framework would be best
  • which approach would be most flexible and manintainable.
Share Improve this question edited Jan 27, 2012 at 16:30 Peter O. 32.9k14 gold badges85 silver badges97 bronze badges asked Dec 20, 2011 at 15:48 sianabananasianabanana 9301 gold badge12 silver badges30 bronze badges 4
  • Are the different sections static or dynamic? – Erik Commented Jan 26, 2012 at 8:24
  • um - well static to the user, dynamic to the administrator. What i mean is, once the user is using the site and as far as the html knows, the sections are going to be static. The coordinates/points/paths for the sections will be dynamically loaded from a database. So that it can be exended with other images/shapes. – sianabanana Commented Jan 26, 2012 at 14:04
  • assuming you will only use line drawings, you might want to load them from a database. I will have a play around with it when I get home from work, nothing too difficult though. – Erik Commented Jan 26, 2012 at 23:58
  • 1 Can you use SVG instead of canvas? svg is made for manipulation via javascript events and saving to db is very simple as it is basically just rendered xml. – Clemens Commented Jan 31, 2012 at 19:41
Add a ment  | 

5 Answers 5

Reset to default 6 +25

I got into similar situation of loading and retrieving data(canvas state) with using Kinectic Js library.

Now I am using fabric js library. https://github./kangax/fabric.js/

It saves the objects' properties or state by canvas.toJSON() method and then reload the canvas with canvas.loadFromJSON() method.

I have played around with it, the example is very basic and not meant for production. You can view an example at http://xisse/shapes.php And download the source at http://xisse/shapes.zip You will need a webserver running php and a mysql database. There is an sql file included in the .zip file. Simply edit the db connection in the shapes.php file and away you go. I will also post the code below:

shapes.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./ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
    <script src="http://www.html5canvastutorials./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>

The 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');

That should get you on your way :)

Svg can t be viewed on some browsers especially mobile browsers, but Raphael Js images can. Use Raphael who is very good library, draw your images in svg use their primitives path, add that data in Raphael drawing functions an vouila you have your image in canvas. I use flex and fxg and for vector images, there is nothing faster then fxg and flash when you need to build interfaces, but these days we are limited to html5 and nasty javascript :) like we went back in 90's

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./reference.html#Paper.path, for colouring them http://raphaeljs./reference.html#Element.attr and for handling events http://raphaeljs./reference.html#Element.click. Given this it'd be possible to store your drawings as a ma separated list of SVG paths, and your colourings as a ma 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.

I would concur with wheresrhys. SVG seems like a better approach for what you want. And out of the SVG libraries out there, raphael allows you to do a lot.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论