- 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="select file" 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">Generate</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; /* background-color: pink; */ border-radius: 5px; overflow: hidden; border: 1px solid #409eff; } .main-left {<!-- --> } .main-mid {<!-- --> width: 200px; height: auto; /* background-color: aliceblue; */ 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 & amp; & amp; cvs. getContext('2d', {<!-- --> willReadFrequently: true }); const ctxHandler = cvsHandler & amp; & amp; 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); // Clear the canvas, otherwise the pictures will overlap 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 () {<!-- --> //Picture zoom ratio, small pictures are enlarged, large pictures are reduced let scale = image.width / cvs.width; // image centering 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); }; } /** * @desc returns the corresponding color value in imageData according to x and y * @param { Number } x * @param { Number } y * @returns {Number} index clicked position index */ function point2Index(x, y) {<!-- --> return (y * cvs. width + x) * 4; } /** * @desc Get the color value of the clicked point through the index * @param {boolean} a */ 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]; } /** * @desc modify similar imageData item data, * @param { Array } clickColor * @param { Array } toChangeColorToRgba * @param { Object } imageData * @returns { Object } new imageData object */ 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; } /** * @desc hex to rgba * @param {string} hex * @returns {boolean} return value is true */ 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]; } /** * @desc * @param {Arrary} color1 * @param {Arrary} color2 * @param {Number} difference difference * @returns {boolean} return boolean */ 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); });
- preview address
gitee code address, click to view