2016-04-28 74 views
0

我有一个画布中的代码,可以帮助我制作气体三角形(duval三角形)。 我需要将代码从canvas转换为svg。 为什么我从canvas转到svg的原因之一是因为我无法在canvas中添加事件处理程序(它的行为像位图),但在svg中我可以做到。转换代码从画布到svg

1.是否有可能?

2.我可以在画布上做同样的事情吗?

3.我应该使用库来帮助我写作svg,对于特定svg库的任何建议吗?

我的代码是基于以下职位: how to create Duval Triangle in canvas

$(function() { 
 

 

 
    var canvas = document.getElementById("canvas"); 
 
    var ctx = canvas.getContext("2d"); 
 

 
    // https://www.researchgate.net/publication/4345236_A_Software_Implementation_of_the_Duval_Triangle_Method 
 

 
    var v0 = { 
 
    x: 58, 
 
    y: 845 
 
    }; 
 
    var v1 = { 
 
    x: 984, 
 
    y: 845 
 
    }; 
 
    var v2 = { 
 
    x: 521, 
 
    y: 41 
 
    }; 
 
    var triangle = [v0, v1, v2]; 
 

 
    // Define all your segments here 
 
    var segments = [{ 
 
    points: [{ 
 
     x: 58, 
 
     y: 845 
 
    }, { 
 
     x: 272, 
 
     y: 845 
 
    }, { 
 
     x: 567, 
 
     y: 333 
 
    }, { 
 
     x: 461, 
 
     y: 150 
 
    }], 
 
    fill: 'rgb(172,236,222)', 
 
    label: { 
 
     text: 'D1', 
 
     cx: 300, 
 
     cy: 645, 
 
     withLine: false, 
 
     endX: null, 
 
     endY: null 
 
    }, 
 
    }, { 
 
    points: [{ 
 
     x: 272, 
 
     y: 845 
 
    }, { 
 
     x: 567, 
 
     y: 333 
 
    }, { 
 
     x: 646, 
 
     y: 468 
 
    }, { 
 
     x: 572, 
 
     y: 597 
 
    }, { 
 
     x: 716, 
 
     y: 845 
 
    }], 
 
    fill: 'deepskyblue', 
 
    label: { 
 
     text: 'D2', 
 
     cx: 490, 
 
     cy: 645, 
 
     withLine: false, 
 
     endX: null, 
 
     endY: null 
 
    }, 
 
    }, { 
 
    points: [{ 
 
     x: 716, 
 
     y: 845 
 
    }, { 
 
     x: 845, 
 
     y: 845 
 
    }, { 
 
     x: 683, 
 
     y: 565 
 
    }, { 
 
     x: 734, 
 
     y: 476 
 
    }, { 
 
     x: 503, 
 
     y: 76 
 
    }, { 
 
     x: 461, 
 
     y: 150 
 
    }, { 
 
     x: 646, 
 
     y: 468 
 
    }, { 
 
     x: 572, 
 
     y: 595 
 
    }], 
 
    fill: 'lightCyan', 
 
    label: { 
 
     text: 'DT', 
 
     cx: 656, 
 
     cy: 645, 
 
     withLine: false, 
 
     endX: 366, 
 
     endY: 120 
 
    }, 
 
    }, { //here - I am in hell.-s5 
 
    points: [{ 
 
     x: 530, 
 
     y: 59 
 
    }, { 
 
     x: 512, 
 
     y: 59 
 
    }, { 
 
     x: 521, 
 
     y: 41 
 
    }], 
 
    fill: 'black', 
 
    label: { 
 
     text: 'PD', 
 
     cx: 600, 
 
     cy: 52, 
 
     withLine: true, 
 
     endX: 520, 
 
     endY: 70 
 
    }, 
 
    }, { 
 
    points: [{ 
 
     x: 595, 
 
     y: 235 
 
    }, { 
 
     x: 614, 
 
     y: 203 
 
    }, { 
 
     x: 530, 
 
     y: 59 
 
    }, { 
 
     x: 512, 
 
     y: 59 
 
    }, { 
 
     x: 503, 
 
     y: 76 
 
    }], 
 
    fill: 'navajoWhite', 
 
    label: { 
 
     text: 'T1', 
 
     cx: 670, 
 
     cy: 140, 
 
     withLine: true, 
 
     endX: 574, 
 
     endY: 105 
 
    }, 
 
    }, { 
 
    points: [{ 
 
     x: 753, 
 
     y: 446 
 
    }, { 
 
     x: 735, 
 
     y: 476 
 
    }, { 
 
     x: 595, 
 
     y: 235 
 
    }, { 
 
     x: 614, 
 
     y: 203 
 
    }], 
 
    fill: 'tan', 
 
    label: { 
 
     text: 'T2', 
 
     cx: 800, 
 
     cy: 290, 
 
     withLine: true, 
 
     endX: 662, 
 
     endY: 120 
 
    }, 
 
    }, { 
 
    points: [{ 
 
     x: 845, 
 
     y: 845 
 
    }, { 
 
     x: 683, 
 
     y: 565 
 
    }, { 
 
     x: 753, 
 
     y: 446 
 
    }, { 
 
     x: 984, 
 
     y: 845 
 
    }], 
 
    fill: 'peru', 
 
    label: { 
 
     text: 'T3', 
 
     cx: 800, 
 
     cy: 645, 
 
     withLine: false, 
 
     endX: null, 
 
     endY: null 
 
    }, 
 
    }, ]; 
 

 
    // label styles 
 
    var labelfontsize = 12; 
 
    var labelfontface = 'verdana'; 
 
    var labelpadding = 3; 
 

 
    // pre-create a canvas-image of the arrowhead 
 
    var arrowheadLength = 10; 
 
    var arrowheadWidth = 8; 
 
    var arrowhead = document.createElement('canvas'); 
 
    premakeArrowhead(); 
 

 
    var legendTexts = ['PD = Partial Discharge', 
 
    'DT = Discharges and Thermal', 
 
    'T1 = Thermal fault T < 300 ℃', 
 
    'T2 = Thermal fault 300 ℃ < T < 700 ℃', 
 
    'T3 = Thermal fault T > 700 ℃', 
 
    'D1 = Discharges of low energy', 
 
    'D2 = Discharges of high energy' 
 
    ]; 
 

 

 
    // start drawing 
 
    ///////////////////// 
 

 

 
    // draw colored segments inside triangle 
 
    for (var i = 0; i < segments.length; i++) { 
 
    drawSegment(segments[i]); 
 
    } 
 
    // draw ticklines 
 
    ticklines(v0, v1, 9, Math.PI * 1.2, 20); 
 
    ticklines(v1, v2, 9, Math.PI * 3/4, 20); 
 
    ticklines(v2, v0, 9, Math.PI * 2, 20); 
 
    // molecules 
 
    moleculeLabel(v0, v1, 100, Math.PI/2, '% CH4'); 
 
    moleculeLabel(v1, v2, 100, 0, '% C2H4'); 
 
    moleculeLabel(v2, v0, 100, Math.PI, '% C2H2'); 
 
    // draw outer triangle 
 
    drawTriangle(triangle); 
 
    // draw legend 
 
    drawLegend(legendTexts, 10, 10, 12.86); 
 
    drawCircle(canvas.width/3, canvas.height/2, 2.5, 'red'); 
 
    // end drawing 
 
    ///////////////////// 
 

 
    function drawCircle(point1, point2, radius, color) { 
 
    ctx.beginPath(); 
 
    ctx.arc(point1, point2, radius, 0, 2 * Math.PI, false); 
 
    ctx.fillStyle = color; 
 
    ctx.fill(); 
 
    } 
 

 
    function drawSegment(s) { 
 
    // draw and fill the segment path 
 
    ctx.beginPath(); 
 
    ctx.moveTo(s.points[0].x, s.points[0].y); 
 
    for (var i = 1; i < s.points.length; i++) { 
 
     ctx.lineTo(s.points[i].x, s.points[i].y); 
 
    } 
 
    ctx.closePath(); 
 
    ctx.fillStyle = s.fill; 
 
    ctx.fill(); 
 
    ctx.lineWidth = 2; 
 
    ctx.strokeStyle = 'black'; 
 
    ctx.stroke(); 
 
    // draw segment's box label 
 
    if (s.label.withLine) { 
 
     lineBoxedLabel(s, labelfontsize, labelfontface, labelpadding); 
 
    } else { 
 
     boxedLabel(s, labelfontsize, labelfontface, labelpadding); 
 
    } 
 
    } 
 

 

 
    function moleculeLabel(start, end, offsetLength, angle, text) { 
 
    ctx.textAlign = 'center'; 
 
    ctx.textBaseline = 'middle' 
 
    ctx.font = '14px verdana'; 
 
    var dx = end.x - start.x; 
 
    var dy = end.y - start.y; 
 
    var x0 = parseInt(start.x + dx * 0.50); 
 
    var y0 = parseInt(start.y + dy * 0.50); 
 
    var x1 = parseInt(x0 + offsetLength * Math.cos(angle)); 
 
    var y1 = parseInt(y0 + offsetLength * Math.sin(angle)); 
 
    ctx.fillStyle = 'black'; 
 
    ctx.fillText(text, x1, y1); 
 
    // arrow 
 
    var x0 = parseInt(start.x + dx * 0.35); 
 
    var y0 = parseInt(start.y + dy * 0.35); 
 
    var x1 = parseInt(x0 + 50 * Math.cos(angle)); 
 
    var y1 = parseInt(y0 + 50 * Math.sin(angle)); 
 
    var x2 = parseInt(start.x + dx * 0.65); 
 
    var y2 = parseInt(start.y + dy * 0.65); 
 
    var x3 = parseInt(x2 + 50 * Math.cos(angle)); 
 
    var y3 = parseInt(y2 + 50 * Math.sin(angle)); 
 
    ctx.beginPath(); 
 
    ctx.moveTo(x1, y1); 
 
    ctx.lineTo(x3, y3); 
 
    ctx.strokeStyle = 'black'; 
 
    ctx.lineWidth = 1; 
 
    ctx.stroke(); 
 
    var angle = Math.atan2(dy, dx); 
 
    ctx.save(); // save 
 
    ctx.translate(x3, y3); 
 
    ctx.rotate(angle); 
 
    ctx.drawImage(arrowhead, -arrowheadLength, -arrowheadWidth/2); 
 
    ctx.restore() 
 
    } 
 

 

 
    function boxedLabel(s, fontsize, fontface, padding) { 
 
    var centerX = s.label.cx; 
 
    var centerY = s.label.cy; 
 
    var text = s.label.text; 
 
    ctx.textAlign = 'center'; 
 
    ctx.textBaseline = 'middle' 
 
    ctx.font = fontsize + 'px ' + fontface 
 
    var textwidth = ctx.measureText(text).width; 
 
    var textheight = fontsize * 1.286; 
 
    var leftX = centerX - textwidth/2 - padding; 
 
    var topY = centerY - textheight/2 - padding; 
 
    ctx.fillStyle = 'white'; 
 
    ctx.fillRect(leftX, topY, textwidth + padding * 2, textheight + padding * 2); 
 
    ctx.lineWidth = 1; 
 
    ctx.strokeRect(leftX, topY, textwidth + padding * 2, textheight + padding * 2); 
 
    ctx.fillStyle = 'black'; 
 
    ctx.fillText(text, centerX, centerY); 
 
    } 
 

 

 
    function lineBoxedLabel(s, fontsize, fontface, padding) { 
 
    var centerX = s.label.cx; 
 
    var centerY = s.label.cy; 
 
    var text = s.label.text; 
 
    var lineToX = s.label.endX; 
 
    var lineToY = s.label.endY; 
 
    ctx.textAlign = 'center'; 
 
    ctx.textBaseline = 'middle' 
 
    ctx.font = fontsize + 'px ' + fontface 
 
    var textwidth = ctx.measureText(text).width; 
 
    var textheight = fontsize * 1.286; 
 
    var leftX = centerX - textwidth/2 - padding; 
 
    var topY = centerY - textheight/2 - padding; 
 
    // the line 
 
    ctx.beginPath(); 
 
    ctx.moveTo(leftX, topY + textheight/2); 
 
    ctx.lineTo(lineToX, topY + textheight/2); 
 
    ctx.strokeStyle = 'black'; 
 
    ctx.lineWidth = 1; 
 
    ctx.stroke(); 
 
    // the boxed text 
 
    ctx.fillStyle = 'white'; 
 
    ctx.fillRect(leftX, topY, textwidth + padding * 2, textheight + padding * 2); 
 
    ctx.strokeRect(leftX, topY, textwidth + padding * 2, textheight + padding * 2); 
 
    ctx.fillStyle = 'black'; 
 
    ctx.fillText(text, centerX, centerY); 
 
    } 
 

 

 
    function ticklines(start, end, count, angle, length) { 
 
    var dx = end.x - start.x; 
 
    var dy = end.y - start.y; 
 
    ctx.lineWidth = 1; 
 
    for (var i = 1; i < count; i++) { 
 
     var x0 = parseInt(start.x + dx * i/count); 
 
     var y0 = parseInt(start.y + dy * i/count); 
 
     var x1 = parseInt(x0 + length * Math.cos(angle)); 
 
     var y1 = parseInt(y0 + length * Math.sin(angle)); 
 
     ctx.beginPath(); 
 
     ctx.moveTo(x0, y0); 
 
     ctx.lineTo(x1, y1); 
 
     ctx.stroke(); 
 
     if (i == 2 || i == 4 || i == 6 || i == 8) { 
 
     var labelOffset = length * 3/4; 
 
     var x1 = parseInt(x0 - labelOffset * Math.cos(angle)); 
 
     var y1 = parseInt(y0 - labelOffset * Math.sin(angle)); 
 
     ctx.fillStyle = 'black'; 
 
     ctx.fillText(parseInt(i * 10), x1, y1); 
 
     } 
 
    } 
 
    } 
 

 

 
    function premakeArrowhead() { 
 
    var actx = arrowhead.getContext('2d'); 
 
    arrowhead.width = arrowheadLength; 
 
    arrowhead.height = arrowheadWidth; 
 
    actx.beginPath(); 
 
    actx.moveTo(0, 0); 
 
    actx.lineTo(arrowheadLength, arrowheadWidth/2); 
 
    actx.lineTo(0, arrowheadWidth); 
 
    actx.closePath(); 
 
    actx.fillStyle = 'black'; 
 
    actx.fill(); 
 
    } 
 

 

 
    function drawTriangle(t) { 
 
    ctx.beginPath(); 
 
    ctx.moveTo(t[0].x, t[0].y); 
 
    ctx.lineTo(t[1].x, t[1].y); 
 
    ctx.lineTo(t[2].x, t[2].y); 
 
    ctx.closePath(); 
 
    ctx.strokeStyle = 'black'; 
 
    ctx.lineWidth = 2; 
 
    ctx.stroke(); 
 
    } 
 

 

 
    function drawLegend(texts, x, y, lineheight) { 
 
    ctx.textAlign = 'left'; 
 
    ctx.textBaseline = 'top'; 
 
    ctx.fillStyle = 'black'; 
 
    ctx.font = '12px arial'; 
 
    for (var i = 0; i < texts.length; i++) { 
 
     ctx.fillText(texts[i], x, y + i * lineheight); 
 
    } 
 
    } 
 
})
body { 
 
    background-color: ivory; 
 
    padding: 10px; 
 
} 
 
#canvas { 
 
    border: 1px solid red; 
 
    margin: 0 auto; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<canvas id="canvas" width=1024 height=1020></canvas>

+0

也可参考小提琴“http://jsfiddle.net/Nofiden/sz72zzan/” – Nofi

回答

0
  1. 是的,这是可能的。

  2. 你可以在svg上做比canvas更多的事情。

  3. 您可以尝试SVG.JS库。它重量轻,易于使用。

+0

好的,请给我看一个完整的3D游戏在SVG。如果你想坚持2d的上下文,简单地告诉我你如何在svg中进行像素操作。你可以在svg上做一些你不能在canvas上做的事情(基本上是导入HTML节点),但是你可以在画布上做很多事情,而你不能在svg上做。 – Kaiido

1

尝试面料JS帆布转换为SVG。 JsFiddle

HTML

<canvas id="canvas" width=1024 height=1020></canvas> 
<button id="canvas2svg">Canvas 2 SVG</button> 

JS

var canvas = new fabric.Canvas('canvas', { isDrawingMode: true }); 
    //var canvas = document.getElementById("canvas"); 
    var ctx = canvas.getContext("2d"); 
$("#canvas2svg").click(function(){ 
    canvas.isDrawingMode = false; 
    alert(canvas.toSVG()); 
}); 

JsFiddle

Also refer this example fiddle

+0

的问题是,它是SVG的形象,我不能事件侦听器添加到此SVG组件。我不能将这个svg分解成一个小部件,它就像一个图像一样。 – Brk

+0

我可以使用fabricjs添加事件处理程序吗?如果是的话,你解决了我的问题,我可以吗? – Brk

+0

是的,最好使用fabricJs处理程序。 – Nofi