- html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/theme-chalk/index.css" rel="stylesheet" />
<link rel="stylesheet" href="./css/index.css" />
<title>Document</title>
</head>
<body>
<div class="header">
<input type="file" placeholder="选择文件" id="imageUpload" accept="image/*" />
</div>
<div class="main">
<div class="main-left main-width">
<canvas id="canvas"></canvas>
</div>
<div class="main-mid">
<input type="color" id="picker" />
<button id="generate" class="el-button el-button--primary el-button--mini">生成</button>
</div>
<div class="main-right main-width">
<canvas id="canvas-handle"></canvas>
</div>
</div>
<script src="./js/canvas.js"></script>
</body>
</html>
- css
html,
body {
padding: 0;
margin: 0;
}
.main {
width: 100%;
margin-top: 50px;
display: flex;
justify-content: space-around;
}
.main-width {
width: 500px;
height: 500px;
border-radius: 5px;
overflow: hidden;
border: 1px solid #409eff;
}
.main-left {
}
.main-mid {
width: 200px;
height: auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.main-right {
}
.header {
height: 60px;
text-align: center;
line-height: 60px;
}
#picker {
margin-bottom: 10px;
}
- javascript
const cvs = document.getElementById('canvas');
const cvsHandler = document.getElementById('canvas-handle');
const fileUpload = document.getElementById('imageUpload');
const ctx = cvs && cvs.getContext('2d', { willReadFrequently: true });
const ctxHandler = cvsHandler && cvsHandler.getContext('2d', { willReadFrequently: true });
const picker = document.getElementById('picker');
const generateBtn = document.getElementById('generate');
cvs.width = cvsHandler.width = cvs.parentNode.clientWidth;
cvs.height = cvsHandler.height = cvs.parentNode.clientHeight;
let url = '';
let clickColor = [];
fileUpload.addEventListener('change', function (e) {
const file = e.target.files[0];
url = URL.createObjectURL(file);
ctx.clearRect(0, 0, cvs.width, cvs.height);
ctxHandler.clearRect(0, 0, cvs.width, cvs.height);
init();
});
function init() {
const image = new Image();
image.src = url;
image.onload = function () {
let scale = image.width / cvs.width;
let x = image.width / scale >= cvs.width ? 0 : (cvs.width - image.width / scale) / 2;
let y = image.height / scale >= cvs.height ? 0 : (cvs.height - image.height / scale) / 2;
ctx.drawImage(image, 0, 0, image.width, image.height, x, y, image.width / scale, image.height / scale);
ctxHandler.drawImage(image, 0, 0, image.width, image.height, x, y, image.width / scale, image.height / scale);
};
}
function point2Index(x, y) {
return (y * cvs.width + x) * 4;
}
function getColorByIndex(index, imageData) {
const r = imageData.data[index];
const g = imageData.data[index + 1];
const b = imageData.data[index + 2];
const a = imageData.data[index + 3];
return [r, g, b, a];
}
function getImageData(clickColor, toChangeColorToRgba, imageData) {
const data = imageData.data || [];
for (let i = 0, len = data.length; i < len; i += 4) {
const isSim = isSimilar(clickColor, data.slice(i, i + 4), 30);
if (isSim) {
data[i] = toChangeColorToRgba[0];
data[i + 1] = toChangeColorToRgba[1];
data[i + 2] = toChangeColorToRgba[2];
data[i + 3] = toChangeColorToRgba[3];
}
}
return imageData;
}
function hexToRgba(hex, opacity = 255) {
hex = hex.replace('#', '');
let r = parseInt(hex.substring(0, 2), 16);
let g = parseInt(hex.substring(2, 4), 16);
let b = parseInt(hex.substring(4, 6), 16);
return [r, g, b, opacity];
}
function isSimilar(color1, color2, difference) {
let diff = Math.abs(color1[0] - color2[0]) + Math.abs(color1[1] - color2[1]) + Math.abs(color1[2] - color2[2]) + Math.abs(color1[3] - color2[3]);
return diff < difference;
}
generateBtn.addEventListener('click', function () {
if (!clickColor.length) return;
const imageData = ctx.getImageData(0, 0, cvs.width, cvs.height);
const toChangeColorToRgba = hexToRgba(picker.value);
const newImageData = getImageData(clickColor, toChangeColorToRgba, imageData);
ctxHandler.putImageData(newImageData, 0, 0);
});
cvs.addEventListener('click', function (e) {
if (!url) return;
const x = e.offsetX;
const y = e.offsetY;
const imageData = ctx.getImageData(0, 0, cvs.width, cvs.height);
const index = point2Index(x, y);
clickColor = getColorByIndex(index, imageData);
});
- 预览地址
gitee代码地址,点击即可查看