简体   繁体   中英

Convert code from canvas to svg

I have a code in canvas which help me in making gas triangles(duval triangles). I need to convert the code from canvas to svg. One of the reason why I moving from canvas to svg, is because I can't add event handlers in canvas(which act like bitmap) but in svg I can do it.

1.Is it possible?

2.Can I do the same things in canvas also in svg?

3.Should I use libraries to help me in writing svg, any recommendations for specific svg library?

My code is based on the following post: 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>

Try fabric JS to convert canvas to 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

  1. Yes it is possible.

  2. You can do more things on svg than on canvas.

  3. You can try SVG.JS library. It is lightweight and easy to use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM