英文:
How to create linear gradient with thousands of properties in JS
问题
我正在制作一个效率低下的重新绘制工具,它会获取画布上每个像素的颜色值,并将该数据插入到一个单独的div的线性渐变CSS属性中。我希望线性渐变可以创建一个不会褪色的效果,每个像素都会有一个单独的颜色。我也不知道线性渐变如何与我的像素颜色值对齐,因为它是逐行读取的。
**我的其他值,如百分比和数据,是任意的,因为我已经解决了这个问题**
var data=(img_ctx.getImageData(x,y,1,1).data);
draw.style.background+=" ,linear-gradient(0deg, "+Math.floor(percent)+"%, rgba("+data+")";
我只是得到了一个没有背景样式属性的div,我添加了逗号以允许多种颜色,只是不太确定如何充分利用线性渐变来解决这个问题。
英文:
I'm making a really in-efficient redrawing tool that takes each pixel of a canvas and takes it's color values and plugs that data into a linear gradient CSS property on a separate div. I want the linear gradient to create a non-fading effect where every pixel is going to have a separate color. I also don't know how the linear gradient will align with my pixel-color values since it reads every line one by one.
My other values like percent and data are arbitrary because I already have that figured out
var data=(img_ctx.getImageData(x,y,1,1).data);
draw.style.background+=" ,linear-gradient(0deg, "+Math.floor(percent)+"%, rgba("+data+")";
I just got a div that has no style properties for background, and I added the comma to allow multiple colors, I'm just not sure how to use linear gradient well enough to figure this out.
答案1
得分: 1
线性渐变只有一个单一轴,并在垂直方向上填充其容器。换句话说,你只能控制沿着该轴的颜色宽度,这使得在大于1像素的div中创建一个1像素 x 1像素的颜色变得不可能。
因此,实现重绘的唯一方法是创建一个高度为1像素的div堆栈(或者宽度为1像素的列)。
然后,通过为每种颜色添加两个停止点来将颜色限制在主轴上的1像素位置,分别指示开始和结束。
英文:
Linear gradients have only a single axis and fill their container in the perpendicular direction. In other words, you can only control the width of a color along that axis, making it impossible to create a 1px x 1px color within a div larger than 1px.
So the only way to achieve the redraw is to create a stack of divs with 1px of height (or columns with 1px width).
You can then contain the colors to 1px along the main axis by adding two stops for each color indicating the start and end along the main axis.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const scale = 0.1;
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = onload;
fetch('https://i.kym-cdn.com/entries/icons/original/000/006/428/637738.jpg')
.then((res) => res.blob())
.then((blob) => (img.src = URL.createObjectURL(blob)));
function onload() {
const w = img.width * scale;
const h = img.height * scale;
canvas.width = w;
canvas.height = h;
canvas.style.width = w.toString() + 'px';
canvas.style.height = h.toString() + 'px';
ctx.drawImage(img, 0, 0, w, h);
const pixelData = Array.from(ctx.getImageData(0, 0, w, h).data);
for (let row = 0; row < h; row++) {
const rowDiv = document.createElement('div');
rowDiv.style.width = w.toString() + 'px';
rowDiv.style.height = '1px';
const rowStart = row * w * 4;
let background = 'linear-gradient(to right,';
for (let col = 0; col < w; col++) {
const pixelStart = rowStart + col * 4;
background +=
'rgba(' +
pixelData[pixelStart] +
',' +
pixelData[pixelStart + 1] +
',' +
pixelData[pixelStart + 2] +
',' +
pixelData[pixelStart + 3] +
')' + col + 'px ' + (col + 1) + 'px,';
}
rowDiv.style.background = background.slice(0, -1) + ')';
document.body.append(rowDiv);
}
}
<!-- language: lang-html -->
<h1>Canvas</h1>
<canvas></canvas>
<h1>Gradients</h1>
<!-- end snippet -->
But at this point you might as well just make a div for every pixel.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论