Html5 Сложная форма и события - рекомендуем подход для удобного и гибкого кода - PullRequest
2 голосов
/ 20 декабря 2011

У меня есть требование создать холст HTML5 для захвата некоторых входных данных.Я хотел бы сделать рисование линий (черная линия на белом) и позволить пользователю раскрасить сечения.

Затем я хотел бы иметь возможность получить эти данные в конце, чтобы обработать их на сервере.сторона, и, таким образом, его можно будет визуализировать позже.

Я хотел бы сохранить данные для визуализации изображения в базе данных, чтобы потенциально можно было нарисовать любое изображение.

Iзаглянул в HTML5 и тег холста.Также в Кинетической JS библиотеке.Я смог сделать быструю демонстрацию того, что мне нужно.

http://jsfiddle.net/6qskx/

Из того, что я имею в демоверсии, этот подход будет очень сложно поддерживать и сложно настроить изображенияво-первых, так как каждый раздел должен был бы быть разработан и прорисован так, чтобы к ним можно было добавлять события.

Мой вопрос: есть ли у кого-нибудь опыт работы с чем-либо подобным или с любой из множества фреймворков?предложить:

  • какая структура будет лучше
  • какой подход будет наиболее гибким и осуществимым.

Ответы [ 5 ]

6 голосов
/ 29 января 2012

Я попал в аналогичную ситуацию загрузки и извлечения данных (состояние холста) с использованием библиотеки Kinectic Js.

Теперь я использую библиотеку Fabric JS.https://github.com/kangax/fabric.js/

Сохраняет свойства или состояние объектов методом canvas.toJSON () , а затем перезагружает холст с помощью canvas.loadFromJSON () метод.

1 голос
/ 05 мая 2012

Svg нельзя просматривать в некоторых браузерах, особенно в мобильных, но изображения Raphael Js могут. Используйте Рафаэля, который является очень хорошей библиотекой, рисуйте ваши изображения в svg, используйте путь их примитивов, добавьте эти данные в функции рисования Рафаэля, если у вас есть изображение на холсте. Я использую flex и fxg, и для векторных изображений нет ничего быстрее, чем fxg и flash, когда вам нужно создавать интерфейсы, но в наши дни мы ограничены html5 и неприятным javascript :), как мы вернулись в 90-х

1 голос
/ 27 января 2012

Я поиграл с этим, пример очень простой и не предназначен для производства. Вы можете просмотреть пример на http://xisse.net/shapes.php И скачать исходник на http://xisse.net/shapes.zip Вам понадобится веб-сервер с php и база данных mysql. В файл .zip включен файл sql. Просто отредактируйте соединение db в файле shape.php и все готово. Я также отправлю код ниже:

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

Это должно помочь вам в этом:)

0 голосов
/ 01 февраля 2012

Я бы согласился с Wheresrhys. SVG кажется лучшим подходом к тому, что вы хотите. И из библиотек SVG Рафаэль позволяет вам многое делать.

0 голосов
/ 01 февраля 2012

Я удивлен, что никто еще не упомянул Рафаэль , поскольку, как мне кажется, это фактический стандарт взаимодействия javascript / canvas (по крайней мере, там, где я работаю).

Он имеет простой синтаксис (используя строки пути SVG) для рисования / хранения линий / многоугольников http://raphaeljs.com/reference.html#Paper.path, для их раскрашивания http://raphaeljs.com/reference.html#Element.attr и для обработки событий http://raphaeljs.com/reference.html#Element.click. Учитывая это, это было бы возможносохранить ваши рисунки в виде списка разделенных запятыми путей SVG, а ваши раскраски - в виде списка значений, разделенных запятыми (помещать в массив при просмотре / раскрашивании изображения), причем каждое значение соответствует одному из ваших путей '

Документация rapahel немного устрашает, поскольку API в последнее время значительно вырос, и не слишком много указаний на то, где искать что-то (даже если вы хорошо знали старый API), но демоверсии в домашних условиях.страница очень полезна для знакомства с API.

...