I am using a circular graph in a canvas following the process shown in codepen As you can see, the circle is blurred out when I zoom in page. I want to get the line high resolution. How can I do it in a way that It does not blur after zooming in the page. Js code I am using is given below:
$(document).ready(function(e) {
var el = document.getElementById('graph-1'); // get canvas
var options = {
percent: el.getAttribute('data-percent') ,
size: el.getAttribute('data-size') , /*|| 177*/
lineWidth: el.getAttribute('data-line') /*|| 4*/,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var paragrph = document.createElement('p');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#aeb4bb', options.lineWidth, 100 / 100);
drawCircle('#006bcf', options.lineWidth, options.percent / 100);
});
HTML code:
<div id="graph-1" data-percent="85.25" data-size="177" data-line="7"> </div>
You can use window.devicePixelRatio
to get the amount of zoom and use the window.onresize
event to redraw when there is a zoom (zoom changes window size)
See MDN devicePixelRatio for browser support.
Copy of some of your code with modifications to demonstrate how to scale to different pixel ratios via the window.onresize
event.
Note ES6 code requires transpiler for legacy browsers.
// helper functions unrelated to answer
const getElementDataSet = (el, data = {}) => {Object.keys(el.dataset).forEach(key => {data[key] = el.dataset[key]}); return data }
const assignProps = (obj, props) => { Object.keys(props).forEach(key => obj[key] = props[key]);}
const _$ = (name,props) => { const el = document.createElement(name); if (props) { assignProps(el, props) } return el }
const _A$ = (container,el) => {container.appendChild(el); return el }
// end of helper functions unrelated to answer
// Get graph container
const el = graph1;
// defaults and get options
const options = getElementDataSet(el, {
percent: 0, size: 100, lineWidth : 5, rotate: 0
}
);
// create elements and add to graph container
const elements = {
canvas : _A$(el, _$('canvas',{width : options.size, height : options.size})),
display : _A$(el, _$('div',{textContent : options.percent + '%'})),
}
const ctx = elements.canvas.getContext('2d');
function resizeCanvas(){
elements.canvas.style.height = elements.canvas.style.width = options.startSize + "px";
elements.canvas.height = elements.canvas.width = options.size;
}
function drawGraph(){
function drawCircle(color, percent = options.percent / 100) {
ctx.setTransform(1,0,0,1,options.size / 2, options.size / 2);
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
var radius = (options.size - options.lineWidth) / 2;
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = options.lineWidth
ctx.stroke();
};
const scale = devicePixelRatio;
options.size = Math.floor(options.startSize * scale);
options.lineWidth = Math.floor(options.startLineWidth * scale);
resizeCanvas();
drawCircle('#aeb4bb',100);
drawCircle('#006bcf');
};
// remember the start scalable values
options.startSize = options.size;
options.startLineWidth = options.lineWidth;
drawGraph();
// listen to resize events and scale as needed
addEventListener("resize", drawGraph );
canvas {
border: 2px solid black;
}
<div id="graph1" data-percent="85.25" data-size="177" data-line-width="7"> </div>