我将开始研究一个新项目,该项目要求我根据多边形选择裁剪图像。挑战是允许前端用户能够快速选择图像中的区域然后裁剪它。为了让用户更轻松地完成这个过程,我想提供一些类似于photoshop中魔术棒工具的功能。
我找到了这个图书馆 - https://github.com/Tamersoul/magic-wand-js
这很好用,但只允许我选择一次区域。
我的问题是,是否可以添加多个选项的功能,并从已选择的区域中删除选择。
检查这个演示小提琴,看看我指的是什么 - jsfiddle(dot)net / Tamersoul / dr7Dw /
答案 0 :(得分:4)
$(function() {
var colorThreshold = 15,
blurRadius = 5,
simplifyTolerant = 0,
simplifyCount = 30,
hatchLength = 4,
hatchOffset = 0,
imageInfo = null,
cacheInd = null,
cacheInds = [],
downPoint = null,
mask = null,
masks = [],
allowDraw = false,
currentThreshold = colorThreshold;
$('#upload').on('change', function () {
var inp = this;
if (inp.files && inp.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
var img = $('#test');
img.attr('src', e.target.result);
img.on('load', function() {
resetCache();
var canvas = $('#canvas')[0];
imageInfo = {
width: img.width(),
height: img.height(),
context: canvas.getContext("2d")
};
canvas.width = imageInfo.width;
canvas.height = imageInfo.height;
var tempCanvas = document.createElement('canvas'),
tempCtx = tempCanvas.getContext("2d");
tempCanvas.width = imageInfo.width;
tempCanvas.height = imageInfo.height;
tempCtx.drawImage(img[0], 0, 0);
imageInfo.data = tempCtx.getImageData(0, 0, imageInfo.width, imageInfo.height).data;
});
};
reader.readAsDataURL(inp.files[0]);
}
});
$('#blur').on('change keyup', function () {
blurRadius = Number($(this).val()) || 0;
magic();
});
$('#threshold').on('change keyup', function () {
currentThreshold = Number($(this).val()) || 0;
magic();
});
$('#canvas').on('click', function (e) {
var p = $(e.target).offset(),
x = Math.round((e.clientX || e.pageX) - p.left),
y = Math.round((e.clientY || e.pageY) - p.top);
downPoint = { x: x, y: y };
magic();
});
var magic = function () {
if (imageInfo) {
var image = {
data: imageInfo.data,
width: imageInfo.width,
height: imageInfo.height,
bytes: 4
};
mask = MagicWand.floodFill(image, downPoint.x, downPoint.y, currentThreshold);
mask = MagicWand.gaussBlurOnlyBorder(mask, blurRadius);
masks.push(mask);
cacheInds.push(MagicWand.getBorderIndices(mask));
drawBorder(true);
}
};
var drawBorder = function () {
if (masks.length) {
var x, y, k, i, j, m,
w = imageInfo.width,
h = imageInfo.height,
ctx = imageInfo.context,
imgData = ctx.createImageData(w, h),
res = imgData.data;
ctx.clearRect(0, 0, w, h);
for (m = 0; m < masks.length; m++) {
cacheInd = cacheInds[m];
for (j = 0; j < cacheInd.length; j++) {
i = cacheInd[j];
x = i % w; // calc x by index
y = (i - x) / w; // calc y by index
k = (y * w + x) * 4;
if ((x + y + hatchOffset) % (hatchLength * 2) < hatchLength) {
// detect hatch color
res[k + 3] = 255; // black, change only alpha
} else {
res[k] = 255; // white
res[k + 1] = 255;
res[k + 2] = 255;
res[k + 3] = 255;
}
}
}
ctx.putImageData(imgData, 0, 0);
}
};
setInterval(function () {
hatchOffset = (hatchOffset + 1) % (hatchLength * 2);
drawBorder();
}, 100);
$('#trace').on('click', function () {
var ctx = imageInfo.context;
ctx.clearRect(0, 0, imageInfo.width, imageInfo.height);
for (var m = 0; m < masks.length; m++) {
// draw contours
var i, j, ps, cs = MagicWand.traceContours(masks[m]);
cs = MagicWand.simplifyContours(cs, simplifyTolerant, simplifyCount);
//inner
ctx.beginPath();
for (i = 0; i < cs.length; i++) {
if (cs[i].inner) {
ps = cs[i].points;
ctx.moveTo(ps[0].x, ps[0].y);
for (j = 1; j < ps.length; j++) {
ctx.lineTo(ps[j].x, ps[j].y);
}
}
}
ctx.strokeStyle = 'red';
ctx.stroke();
//outer
ctx.beginPath();
for (i = 0; i < cs.length; i++) {
if (!cs[i].inner) {
ps = cs[i].points;
ctx.moveTo(ps[0].x, ps[0].y);
for (j = 1; j < ps.length; j++) {
ctx.lineTo(ps[j].x, ps[j].y);
}
}
}
ctx.strokeStyle = 'blue';
ctx.stroke();
}
resetCache();
});
var resetCache = function () {
mask = null;
masks = [];
cacheInds = [];
};
});
&#13;
#display * {
cursor: crosshair;
position: absolute;
}
&#13;
<!DOCTYPE html>
<html>
<head>
<script src="https://rawgit.com/Tamersoul/magic-wand-js/master/js/magic-wand-min.js"></script>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="controls">
<input id="upload" type="file" accept="image/*"/>
<p>Blur radius
<input value="5" id="blur" type="number"/>
</p>
<p>Threshold
<input value="15" id="threshold" type="number"/>
</p>
<button id="trace">Trace</button>
</div>
<div id="display">
<img id="test"/>
<canvas id="canvas"></canvas>
</div>
</body>
</html>
&#13;