图片裁切,上传,自动匹配颜色。
photoclip插件学习。
使用方法很简单。不过我在使用的过程中遇到几个问题。
1、按官方文档的教程写完代码以后,我的图片只能左右移动,无法上下拖拽,
在竖直方向拖动的话,在拖动结束时会回到初始的竖直方向的位置。
解决方法:本来一直以为是js本地项目的js代码与插件有冲突,不过在改动js后,本地仍然有这个问题。最后发现是本地默认的reset的样式,改不了插件的样式,导致无法正常使用。将 div, dt, dd, li, h3, h4, h5, h6 {
max-height: 100%
}默认样式删除后就可以正常使用了。
2、options.loadStart
type: Function
图片开始加载的回调函数。this 指向当前 PhotoClip 的实例对象,并将正在加载的 file 对象作为参数传入。(如果是使用非 file 的方式加载图片,则该参数为图片的 url)
- options.loadComplete
type: Function
图片加载完成的回调函数。this 指向当前 PhotoClip 的实例对象,并将图片的 <img> 对象作为参数传入。
- options.loadError
type: Function
图片加载失败的回调函数。this 指向当前 PhotoClip 的实例对象,并将错误信息作为第一个参数传入,如果还有其它错误对象或者信息会作为第二个参数传入。
- options.done
type: Function
裁剪完成的回调函数。this 指向当前 PhotoClip 的实例对象,会将裁剪出的图像数据DataURL作为参数传入。
这里应该注意options.done,options.loadComplete和options.loadstart三个函数。
options.done是裁剪完成,执行的函数会有个参数dataurl,里面是图片裁切部分的base64编码。这里回调函数可以用来处理裁切出来的图片数据。
options.loadStart函数是图片开始加载的回调函数。
我使用这个插件实现的基本功能是点击上传按钮可以看到图片预览图,及一个图片的缩略图。上传多张图片时,点击缩略图,可以看到不同的预览图。并且通过点击缩略图的删除按钮,可以删除任何一个图片。
options.loadComplete是加载完成图片时调用的函数function(data) {这个data是预览图的dom节点}
在我的项目中遇到些问题就是在预览多张图片时,在删除某张图片后立刻使用new PhotoClip函数去加载同一张图片,这时是无法加载这张图片的。
这时我使用pc.clear();函数,在上张图片加载完后点击删除图片时clear清除缓存的图片。但此时会发现cleat图片以后,预览的图片img也会消失,无法完成点击图片预览的功能了。所以这时可以在options.loadstart函数中使用pc.clear(),在加载下一张图片前,清除上一张图片,这时不但实现了加载删除的相同的图片,而且可以在删除某个图片时,可以通过点击其他图片实现预览功能。
在项目过程中使用了另一个插件,color-thief.js。是个可以提取图片主题色的js插件。不过在使用过程中发现此插件是自动忽略白色的像素。当你用这个图片提取一张纯白图片中间有一个其他颜色的点时,显示的主题色为这个非白色点的颜色。
所以在学习插件过程中发现
r = pixels[offset + 0];
g = pixels[offset + 1];
b = pixels[offset + 2];
a = pixels[offset + 3];
//If pixel is mostly opaque and not white
if (a >= 125) {
if (!(r > 250 && g > 250 && b > 250)) {
pixelArray.push([r, g, b]);
}
}
在这段代码中,a为某点像素的透明度,从上面代码发现,插件是选取图片的透明度大于125和非白色点来进行取值和处理的。(尚不知道为何作者这么写)。
我对这段代码做了修改,我将if判断删除。
//If pixel is mostly opaque and not white
pixelArray.push([r, g, b]);这时插件取色的点会增多。但是发现还是有些问题,有时无法取到白色的像素,我认为应该是白色的点作为无像素处理的,这时页面会报错,显示palette为null,我便强制改变了此函数。
ColorThief.prototype.getColor = function(sourceImage, quality) {
var palette = this.getPalette(sourceImage, 5, quality);
// 改变无法读取白色边的情况。 -zcj
if(palette==null){
palette = [];
palette[0] = [255,255,255]
}
//两个注释之间为(添加)改变的代码。强制添加了判断。因为主色是很多像素点共同判断的,我将 palette[0] = [255,255,255],我认为只是添加了部分白色的像素点对整体影响应该不大。
var dominantColor = palette[0];
return dominantColor;
};
此插件使用的是中位切分法来进行颜色提取,大家可以点击此链接了解下这种算法。看起来还是很复杂的。https://blog.csdn.net/shanglianlm/article/details/50051269
附上demo代码复制粘贴即可使用
demo是提取图片四个边的宽度为10px主题色。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>demo2</title> <style> #result{ 100px; height: 100px; } .div1{ 100%; height: 100px; } .div2{ 100%; height: 100px; } .div3{ 100%; height: 100px; } </style> </head> <body> <script src="./src/color-thief.js"></script> <script> function readAsDataURL(){ //检验是否为图像文件 var file = document.getElementById("file").files[0]; if(!/image/w+/.test(file.type)){ alert("看清楚,这个需要图片!"); return false; } var reader = new FileReader(); //将文件以Data URL形式读入页面 reader.readAsDataURL(file); reader.onload=function(e){ var result=document.getElementById("result"); let context = document.createElement('canvas'); context.setAttribute('width','200'); context.setAttribute('height','200'); let ctx = context.getContext('2d'); document.querySelector('body').appendChild(context) let image = new Image(); image.src = e.target.result; image.onload = function(){ ctx.drawImage(image,0,0,100,100); let context1 = document.createElement('canvas'); context1.setAttribute('width','200'); context1.setAttribute('height','200'); let ctx1 = context1.getContext('2d'); document.querySelector('body').appendChild(context1); let ctx1data = ctx.getImageData(0,0,100,10); let ctx1data1 = ctx.getImageData(0,0,10,100); let ctx1data2 = ctx.getImageData(90,0,10,100); let ctx1data3 = ctx.getImageData(0,90,100,10); console.log(ctx1data); let context2 = document.createElement('canvas'); context2.setAttribute('width','200'); context2.setAttribute('height','200'); let ctx2 = context2.getContext('2d'); document.querySelector('body').appendChild(context2); let context3 = document.createElement('canvas'); context3.setAttribute('width','200'); context3.setAttribute('height','200'); let ctx3 = context3.getContext('2d'); document.querySelector('body').appendChild(context3); let context4 = document.createElement('canvas'); context4.setAttribute('width','200'); context4.setAttribute('height','200'); let ctx4 = context4.getContext('2d'); document.querySelector('body').appendChild(context4); ctx1.putImageData(ctx1data,0,0); //top ctx2.putImageData(ctx1data1,0,0);//left ctx3.putImageData(ctx1data2,0,0);//right ctx4.putImageData(ctx1data3,0,0);//bottom let colorThief = new ColorThief(); result.style.background = `rgb(${colorThief.getColor(image)[0]},${colorThief.getColor(image)[1]},${colorThief.getColor(image)[2]})`; let maincolor = colorThief.getColor(image); console.log(result.style.background) // console.log(colorThief.getColor(image)); 获取整张图片的主色 console.log(colorThief.getColor(context1)); console.log(colorThief.getColor(context2)); console.log(colorThief.getColor(context3)); console.log(colorThief.getColor(context4)); //获取四个边合在一起的平均色 //div2为四个边的平均 let colorR = (colorThief.getColor(context1)[0]+colorThief.getColor(context2)[0]+colorThief.getColor(context3)[0]+colorThief.getColor(context4)[0])/4 let colorG = (colorThief.getColor(context1)[1]+colorThief.getColor(context2)[1]+colorThief.getColor(context3)[1]+colorThief.getColor(context4)[1])/4 let colorB = (colorThief.getColor(context1)[2]+colorThief.getColor(context2)[2]+colorThief.getColor(context3)[2]+colorThief.getColor(context4)[2])/4 let colorRgb = `(${colorR},${colorG},${colorB})`; //rgb console.log(colorRgb) let showcolorrgb = document.createElement('div'); showcolorrgb.classList.add('div2'); showcolorrgb.innerHTML = '四个边的平均色' showcolorrgb.setAttribute('style',`background:rgb${colorRgb}`); document.querySelector('body').appendChild(showcolorrgb); //在六种颜色中找到最接近匹配颜色的颜色 //黄色:rgb(225,220,50),红色(180,72,78),蓝色(49,121,195),绿色(115,185,85),黑色(14,17,20),白色(255,255,255); //div3为匹配后的颜色 let min = 442; let numorder = 0; let colorlist_Arr = [[225,220,50],[180,72,78],[49,121,195],[115,185,85],[14,17,20],[255,255,255]]; for(let z=0;z<6;z++){ let minA = Math.floor(Math.sqrt(Math.pow(colorlist_Arr[z][0]-colorR,2)+Math.pow(colorlist_Arr[z][1]-colorG,2)+Math.pow(colorlist_Arr[z][2]-colorB,2))); console.log(minA) if(minA<min){ min = minA; numorder = z; } } let divv = document.createElement('div'); divv.classList.add('div3'); divv.innerHTML = '匹配后的颜色,六种颜色之1' divv.setAttribute('style',`background:rgb(${colorlist_Arr[numorder][0]},${colorlist_Arr[numorder][1]},${colorlist_Arr[numorder][2]})`); document.querySelector('body').appendChild(divv); //获取图片中的其他颜色 //div1为图片中其他色,第一个为主色 let colorThiefban = colorThief.getPalette(image, 8); console.log(colorThiefban) for(let i = 0;i<colorThiefban.length;i++){ let div = document.createElement('div'); div.classList.add('div1'); div.innerHTML = '图片中其他色,第一个为主色' div.setAttribute('style',`background:rgb(${colorThiefban[i][0]},${colorThiefban[i][1]},${colorThiefban[i][2]})`); document.querySelector('body').appendChild(div); } //显示文件 // result.innerHTML='<img src="' + e.target.result +'" alt="" />'; } } } </script> <p> <label>请选择一个文件:</label> <input type="file" id="file" /> <input type="button" value="读取图像" onclick="readAsDataURL()" /> </p> <div id="result" name="result">为图片的主色</div> </body> </html>