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 remendations 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");
//
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=".1.1/jquery.min.js"></script>
<canvas id="canvas" width=1024 height=1020></canvas>
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 remendations 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/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./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width=1024 height=1020></canvas>
Yes it is possible.
You can do more things on svg than on canvas.
You can try SVG.JS library. It is lightweight and easy to use.
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