2011-01-05 9 views
11

Estoy trabajando en un proyecto que requiere que los usuarios finales puedan dibujar en el navegador como svg-edit y enviar datos SVG al servidor para su procesamiento.Raphael JS Implementación de una herramienta "Lápiz" de manera eficiente

Empecé a jugar con el marco Raphael y parece prometedor.

Actualmente estoy tratando de implementar una herramienta de lápiz o línea de freeline. Básicamente, estoy dibujando un nuevo camino basado en el porcentaje de movimiento del mouse en el área de dibujo. Sin embargo, al final esto va a crear una gran cantidad de caminos para lidiar.

¿Es posible acortar un camino SVG convirtiendo el movimiento del ratón para usar curva y caminos de línea en lugar de la línea segmentos?

A continuación se muestra proyecto de código que nos prepararon rápidamente para hacer el trabajo ...

// Drawing area size const 
    var SVG_WIDTH = 620; 
    var SVG_HEIGHT = 420; 

    // Compute movement required for new line 
    var xMove = Math.round(SVG_WIDTH * .01); 
    var yMove = Math.round(SVG_HEIGHT * .01); 

    // Min must be 1 
    var X_MOVE = xMove ? xMove : 1; 
    var Y_MOVE = yMove ? yMove : 1; 

    // Coords 
    var start, end, coords = null; 
    var paperOffset = null; 
    var mouseDown = false; 

    // Get drawing area coords 
    function toDrawCoords(coords) { 
    return { 
    x: coords.clientX - paperOffset.left, 
    y: coords.clientY - paperOffset.top 
    }; 
    } 

    $(document).ready(function() { 
    // Get area offset 
    paperOffset = $("#paper").offset(); 
    paperOffset.left = Math.round(paperOffset.left); 
    paperOffset.top = Math.round(paperOffset.top); 
    // Init area 
    var paper = Raphael("paper", 620, 420); 
    // Create draw area 
    var drawArea = paper.rect(0, 0, 619, 419, 10) 
    drawArea.attr({fill: "#666"}); 

    // EVENTS 
    drawArea.mousedown(function (event) { 
    mouseDown = true; 
    start = toDrawCoords(event); 
    $("#startCoords").text("Start coords: " + $.dump(start)); 
    }); 
    drawArea.mouseup(function (event) { 
    mouseDown = false; 
    end = toDrawCoords(event); 
    $("#endCoords").text("End coords: " + $.dump(end)); 
    buildJSON(paper); 
    }); 
    drawArea.mousemove(function (event) { 
    coords = toDrawCoords(event); 
    $("#paperCoords").text("Paper coords: " + $.dump(coords)); 
    // if down and we've at least moved min percentage requirments 
    if (mouseDown) { 
     var xMovement = Math.abs(start.x - coords.x); 
     var yMovement = Math.abs(start.y - coords.y); 
     if (xMovement > X_MOVE || yMovement > Y_MOVE) { 
     paper.path("M{0} {1}L{2} {3}", start.x, start.y, coords.x, coords.y); 
     start = coords; 
     } 
    } 
    }); 


    }); 

Respuesta

3

Tenga una mirada en el algoritmo de Douglas-Peucker para simplificar su línea.

No sé de cualquier aplicación Javascript (aunque googlear me dirigido a los foros para los mapas de Google a los desarrolladores), pero aquí es una aplicación tcl que es bastante fácil de entender: http://wiki.tcl.tk/27610

Y aquí está un artículo de wikipedia que explica el algoritmo (junto con pseudocódigo): http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm

+0

Esto se ve interesante. Sin embargo, imagino que esto hará que mis curvas se vean más segmentadas. –

+0

El algoritmo tiene un valor de error ajustable que puede usar para decidir qué tan cerca quiere que la línea resultante se asemeje a la línea original. El artículo de wikipedia, por supuesto, exagera un poco en sus diagramas para ilustrar cómo funciona el algoritmo. Básicamente cada vez que reduces el número de puntos en una línea, estás haciendo que la línea sea más "segmentada".Al igual que los juegos usan objetos 3D de polígono bajo para mejorar la velocidad. Mismo principio aquí pero en 2D. – slebetman

0

Estoy trabajando en algo similar. Encontré una forma de agregar incrementalmente comandos de ruta por un pequeño bypass de la API de Raphael como se describe en mi respuesta here. En los navegadores modernos en los que probé, esto funciona razonablemente bien, pero el grado en que las líneas se vean fluidas depende de qué tan rápido pueda funcionar el manejador de mousemove.

Puede probar mi método para dibujar trayectorias utilizando segmentos de línea y luego realizar suavizado después de dibujar la ruta dentada inicial (o de alguna manera), podando las coordenadas usando Ramer-Douglas-Peucker como sugirió slebetman, y convirtiendo el resto L s a comandos de curva SVG.

0

Tengo un problema similar, dibujo usando el mouse hacia abajo y el comando M. Luego guardo esa ruta a una base de datos en el servidor. El problema que estoy teniendo tiene que ver con la resolución. Tengo una imagen de fondo donde los usuarios dibujan líneas y formas sobre partes de la imagen, pero si la imagen se muestra en una resolución y las rutas se crean en esa resolución y se vuelven a abrir en una resolución diferente quizás menor, mis caminos se desplazan y son no tiene el tamaño correcto Supongo que lo que estoy preguntando es: ¿hay alguna manera de trazar un camino sobre una imagen y asegurarse de que, independientemente del tamaño de la imagen subyacente, la ruta siga siendo correcta en principio?

Cuestiones relacionadas