[英]How could I change my canvas color wheel so that its edges are smooth like the CSS version?
How could I change my canvas so that it's smooth (I think it's called anti-aliased) like the CSS version?我怎样才能改变我的画布,使它像 CSS 版本一样平滑(我认为它被称为抗锯齿)?
// https://codepen.io/private_akongkj/pen/RwRMzqY?editors=1010 came from https://codepen.io/bantic/pen/zNKopG?editors=0010 and https://medium.com/@bantic/hand-coding-a-color-wheel-with-canvas-78256c9d7d43 function xy2polar(x, y) { const r = Math.sqrt(x * x + y * y); const phi = Math.atan2(y, x); return [r, phi]; } // rad in [-π, π] range // return degree in [0, 360] range function rad2deg(rad) { return ((rad + Math.PI) / (2 * Math.PI)) * 360; } function createColorWheel(canvas) { console.log('createColorWheel(canvas)', canvas); const ctx = canvas.getContext('2d'); const radius = canvas.width / 2; const image = ctx.createImageData(2 * radius, 2 * radius); const data = image.data; for (let x = -radius; x < radius; x++) { for (let y = -radius; y < radius; y++) { const [r, phi] = xy2polar(x, y); if (r > radius) { // skip all (x,y) coordinates that are outside of the circle continue; } const deg = rad2deg(phi); // Figure out the starting index of this pixel in the image data array. const rowLength = 2 * radius; const adjustedX = x + radius; // convert x from [-50, 50] to [0, 100] (the coordinates of the image data array) const adjustedY = y + radius; // convert y from [-50, 50] to [0, 100] (the coordinates of the image data array) const pixelWidth = 4; // each pixel requires 4 slots in the data array const index = (adjustedX + adjustedY * rowLength) * pixelWidth; const hue = deg; const saturation = 1.0; const value = 1.0; const [red, green, blue] = hsv2rgb(hue, saturation, value); const alpha = 255; data[index] = red; data[index + 1] = green; data[index + 2] = blue; data[index + 3] = alpha; } } ctx.putImageData(image, 0, 0); } // hue in range [0, 360] // saturation, value in range [0,1] // return [r,g,b] each in range [0,255] // See: https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV function hsv2rgb(hue, saturation, value) { const chroma = value * saturation; const hue1 = hue / 60; const x = chroma * (1 - Math.abs((hue1 % 2) - 1)); let r1, g1, b1; if (hue1 >= 0 && hue1 <= 1) { [r1, g1, b1] = [chroma, x, 0]; } else if (hue1 >= 1 && hue1 <= 2) { [r1, g1, b1] = [x, chroma, 0]; } else if (hue1 >= 2 && hue1 <= 3) { [r1, g1, b1] = [0, chroma, x]; } else if (hue1 >= 3 && hue1 <= 4) { [r1, g1, b1] = [0, x, chroma]; } else if (hue1 >= 4 && hue1 <= 5) { [r1, g1, b1] = [x, 0, chroma]; } else if (hue1 >= 5 && hue1 <= 6) { [r1, g1, b1] = [chroma, 0, x]; } const m = value - chroma; const [r, g, b] = [r1 + m, g1 + m, b1 + m]; // Change r,g,b values from [0,1] to [0,255] return [255 * r, 255 * g, 255 * b]; } createColorWheel(document.getElementById('canvas'));
#wheel { width: 100px; height: 100px; border-radius: 50%; background: conic-gradient(rgb(255, 0, 0), rgb(255, 255, 0), rgb(0, 255, 0), rgb(0, 255, 255), rgb(0, 0, 255), rgb(255, 0, 255), rgb(255, 0, 0)); transform: rotate(270deg); display: inline-block; }
<div id="wheel"></div><canvas id="canvas" width="100" height="100"></canvas>
Composite your aliased circle with an anti-aliased one:将您的锯齿圈与抗锯齿圈合成:
// https://codepen.io/private_akongkj/pen/RwRMzqY?editors=1010 came from https://codepen.io/bantic/pen/zNKopG?editors=0010 and https://medium.com/@bantic/hand-coding-a-color-wheel-with-canvas-78256c9d7d43 function xy2polar(x, y) { const r = Math.sqrt(x * x + y * y); const phi = Math.atan2(y, x); return [r, phi]; } // rad in [-π, π] range // return degree in [0, 360] range function rad2deg(rad) { return ((rad + Math.PI) / (2 * Math.PI)) * 360; } function createColorWheel(canvas) { console.log('createColorWheel(canvas)', canvas); const ctx = canvas.getContext('2d'); const radius = canvas.width / 2; const image = ctx.createImageData(2 * radius, 2 * radius); const data = image.data; for (let x = -radius; x < radius; x++) { for (let y = -radius; y < radius; y++) { const [r, phi] = xy2polar(x, y); if (r > radius) { // skip all (x,y) coordinates that are outside of the circle continue; } const deg = rad2deg(phi); // Figure out the starting index of this pixel in the image data array. const rowLength = 2 * radius; const adjustedX = x + radius; // convert x from [-50, 50] to [0, 100] (the coordinates of the image data array) const adjustedY = y + radius; // convert y from [-50, 50] to [0, 100] (the coordinates of the image data array) const pixelWidth = 4; // each pixel requires 4 slots in the data array const index = (adjustedX + adjustedY * rowLength) * pixelWidth; const hue = deg; const saturation = 1.0; const value = 1.0; const [red, green, blue] = hsv2rgb(hue, saturation, value); const alpha = 255; data[index] = red; data[index + 1] = green; data[index + 2] = blue; data[index + 3] = alpha; } } ctx.putImageData(image, 0, 0); // apply antialias ctx.beginPath(); ctx.arc(radius+0.5, radius+0.5, radius-0.5, 0, Math.PI*2); ctx.globalCompositeOperation = "destination-in"; ctx.fill(); // revert to defaults ctx.globalCompositeOperation = "source-over"; } // hue in range [0, 360] // saturation, value in range [0,1] // return [r,g,b] each in range [0,255] // See: https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV function hsv2rgb(hue, saturation, value) { const chroma = value * saturation; const hue1 = hue / 60; const x = chroma * (1 - Math.abs((hue1 % 2) - 1)); let r1, g1, b1; if (hue1 >= 0 && hue1 <= 1) { [r1, g1, b1] = [chroma, x, 0]; } else if (hue1 >= 1 && hue1 <= 2) { [r1, g1, b1] = [x, chroma, 0]; } else if (hue1 >= 2 && hue1 <= 3) { [r1, g1, b1] = [0, chroma, x]; } else if (hue1 >= 3 && hue1 <= 4) { [r1, g1, b1] = [0, x, chroma]; } else if (hue1 >= 4 && hue1 <= 5) { [r1, g1, b1] = [x, 0, chroma]; } else if (hue1 >= 5 && hue1 <= 6) { [r1, g1, b1] = [chroma, 0, x]; } const m = value - chroma; const [r, g, b] = [r1 + m, g1 + m, b1 + m]; // Change r,g,b values from [0,1] to [0,255] return [255 * r, 255 * g, 255 * b]; } createColorWheel(document.getElementById('canvas'));
#wheel { width: 100px; height: 100px; border-radius: 50%; background: conic-gradient(rgb(255, 0, 0), rgb(255, 255, 0), rgb(0, 255, 0), rgb(0, 255, 255), rgb(0, 0, 255), rgb(255, 0, 255), rgb(255, 0, 0)); transform: rotate(270deg); display: inline-block; }
<div id="wheel"></div><canvas id="canvas" width="100" height="100"></canvas>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.