JSFiddle - React, Tailwind, and code Playground
by Paul
HTML
<script src="https://unpkg.com/magic-wand-tool@latest/dist/magic-wand.min.js"></script>
<div style="overflow: auto">
<div class="button" onclick="uploadClick()">Upload image and click on it</div>
<div class="button" onclick="trace()">Create polygons by current selection</div>
<div class="button" onclick="paint('FF0000', 0.35)">Paint the selection</div>
<input id="file-upload" type="file" accept="image/*" onchange="imgChange(this)" />
</div>
<div style="overflow: auto">
<div style="float: left; margin-right: 10px;">Blur radius: </div>
<input id="blurRadius" type="text" onchange="onRadiusChange.apply(this, arguments)" style="float: left; width: 20px; margin-right: 10px;"/>
<div id="threshold"></div>
</div>
<div>(hold left mouse button and move to change the color threshold)</div>
<div>(hold the CTRL key to add selection)</div>
<div class='wrapper'>
<div class='content'>
<img id="test-picture" class="picture" />
<canvas class="canvas" id="resultCanvas" onmouseup="onMouseUp.apply(this, arguments)" onmousedown="onMouseDown.apply(this, arguments)" onmousemove="onMouseMove.apply(this, arguments)"></canvas>
</div>
</div>
CSS
.wrapper {
top: 80px;
width: 400px;
height: 350px;
overflow: auto;
}
.content {
position: relative;
}
.canvas {
position: absolute;
}
.canvas:hover {
cursor: default;
}
.picture {
position: absolute;
}
.button {
padding: 4px;
margin: 4px;
border: 1px solid black;
float: left;
}
.button:hover {
background-color: blue;
color: white;
cursor: pointer;
}
#threshold {
width: 95px;
float: left;
}
#file-upload {
display: none;
}
.add-mode {
cursor: copy !important;
}
JavaScript
window.MagicWand = {};
window.onload = function() {
colorThreshold = 15;
blurRadius = 5;
simplifyTolerant = 0;
simplifyCount = 30;
hatchLength = 4;
hatchOffset = 0;
imageInfo = null;
cacheInd = null;
mask = null;
oldMask = null;
downPoint = null;
allowDraw = false;
addMode = false;
currentThreshold = colorThreshold;
document.onkeydown = onKeyDown;
document.onkeyup = onKeyUp;
showThreshold();
document.getElementById("blurRadius").value = blurRadius;
setInterval(function () { hatchTick(); }, 300);
}
function uploadClick() {
document.getElementById("file-upload").click();
}
function onRadiusChange(e) {
blurRadius = e.target.value;
}
function imgChange (inp) {
if (inp.files && inp.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
var img = document.getElementById("test-picture");
img.setAttribute('src', e.target.result);
img.onload = function() {
window.initCanvas(img);
};
}
reader.readAsDataURL(inp.files[0]);
}
}
function initCanvas(img) {
var cvs = document.getElementById("resultCanvas");
cvs.width = img.width;
cvs.height = img.height;
imageInfo = {
width: img.width,
height: img.height,
context: cvs.getContext("2d")
};
mask = null;
var tempCtx = document.createElement("canvas").getContext("2d");
tempCtx.canvas.width = imageInfo.width;
tempCtx.canvas.height = imageInfo.height;
tempCtx.drawImage(img, 0, 0);
imageInfo.data = tempCtx.getImageData(0, 0, imageInfo.width, imageInfo.height);
}
function getMousePosition(e) {
var p = $(e.target).offset(),
x = Math.round((e.clientX || e.pageX) - p.left),
y = Math.round((e.clientY || e.pageY) - p.top);
return { x: x, y: y };
}
function onMouseDown(e) {
if (e.button == 0) {
allowDraw = true;
...