目录
- 逐一击破
- 确定架构
- 图片上传
- 自适应生成对比界面
- 切换对比模式
- 打分功能
- 审核进行提交
- 项目负责人查看问题并改正
- 总结
前言:这是一个实际的需求,因为需要设计师给的原图和同学们制作出来的项目成品图进行比对打分,所以就有了一个图片对比的小工具。
需求分析:
- 设计稿和成品图片上传功能
- 自适应生成对比界面
- 可切换对比模式
- 打分功能
- 打分者提交问题
- 项目负责人查看问题并改正
逐一击破
确定架构
因为只是一个针对性的小工具,后期也不会扩展,不需要上框架,所以直接引入JQ库进行代码开发,为方便本地局域网使用,配置webpack作为启动项。
目录结构如下:
图片上传
新建upload.js
文件,通过构造函数把上传相关方法统一封装在原型上。
相关方法:
- 初始化
- 支持拖拽上传,点击上传
- 适配监听
- 边界判断
自适应生成对比界面
在点击图片对比的时候,界面生成是根据第一张上传的设计稿的比例来确定的,这样就不会出现页面适配问题,部分代码:
// 上传图片
let dragImgUploadOne = new DragImgUpload("#drop_area_one", {
callback: function (files, imgUrl) {
// 屏幕高度
let clientHeight = document.documentElement.clientHeight;
// 屏幕宽度
let clientWidth = document.documentElement.clientWidth;
// 回调函数,可以传递给后台
let file = files[0];
let size = file.size / 1000 + 'kb';
$('.img-name-one span').text(file.name);
$('.img-size-one span').text(size);
$('.bacnimg2').attr("src", imgUrl);
// 创建对象
var img = new Image();
// 改变图片的src
img.src = imgUrl;
img.onload = function(){
let imgHeigt = img.height / (img.width/clientWidth);
let imgWidth = img.width / (img.height / clientHeight);
upimgHeigt = imgHeigt
upimgWidth = imgWidth
// 如果计算出来的高度大于屏幕高度
if(upimgHeigt > clientHeight){
$('.banner-bg2,.bacnimg').css('width',upimgWidth + 'px')
$('.banner-bg2,.bacnimg,.bacnimg2').css('height','100vh')
// 分割边框
$('.banner-bg2').css('border-right', '1px solid #000')
// 适配线的位置
let dragLine = upimgWidth / 2 - 42;
$('.drag-line').css({'left': dragLine })
}else{
// 分割边框
$('.banner-bg2').css('border-bottom', '1px solid #000')
// 动态修改imgHeigt
$('.banner-bg2,.bacnimg,.bacnimg2,.drag-line').css('height',upimgHeigt + 'px')
}
};
}
})
let dragImgUploadTwo = new DragImgUpload("#drop_area_two", {
callback: function (files, imgUrl) {
//回调函数,可以传递给后台等等
let file = files[0];
let size = file.size / 1000 + 'kb'
$('.img-name-two span').text(file.name)
$('.img-size-two span').text(size)
$('.bacnimg').attr("src", imgUrl);
}
})
切换对比模式
对比支持横向对比和竖向对比,当然斜角对比也可以支持,但是没必要,部分代码:
// 图片对比拖拽逻辑
let $drag = $('#drag-line')
$drag.mousedown(function (e) {
//鼠标按下,计算当前元素距离可视区的距离
let disY = e.clientY - $drag[0].offsetTop;
let disX = e.clientX - $drag[0].offsetLeft;
// 判断对比方式
if(comparison){
document.onmousemove = function (e) {
// 极限位置
let imgHeight = $('.banner-bg2').height() - 50;
// 通过事件委托,计算移动的距离
let distanceTop = e.clientY - disY;
if(distanceTop < imgHeight) $drag.css({'top': distanceTop + 'px'});
};
}else{
document.onmousemove = function (e) {
// 极限位置
let imgWidth = $('.banner-bg2').width() - 50;
// 通过事件委托,计算移动的距离
let distanceLeft = e.clientX - disX;
if(distanceLeft < imgWidth) $drag.css({'left': distanceLeft + 'px'});
};
}
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
};
//return false不加的话可能导致黏连,就是拖到一个地方时div粘在鼠标上不下来,相当于onmouseup失效
return false;
});
打分功能
用户点击成品图的某个位置,就会自动生成节点标签,在input标签中输入扣分项和说明,以便开发同学后期更改,部分代码:
// 扣分填写弹窗模板
function anchorPopup(obj = {}) {
let imgAllWidth = $('.banner-bg2').width();
let imgAllHeight = $('.banner-bg2').height();
let objLeft = obj.left;
let objTop = obj.top;
let particularLeft = obj.left;
let particularTop = obj.top;
if (imgAllWidth - 220 < obj.left) {
objLeft = obj.left - 230
objTop = obj.top + 15
// 计算生产模式打分文字位置
particularLeft = obj.left - 165
particularTop = obj.top
}
if (imgAllHeight - 200 < obj.top) {
objTop = obj.top - 200
// 计算生产模式打分文字位置
particularTop = obj.top -100
}
// 生成扣分填写窗口,重复使用的
$('.anchor-popup-content').html(`
<div class="anchor-popup" style="top:${objTop + 8 + 'px'};left:${objLeft + 20 + 'px'};z-index: -1;">
<p><span style = "color:#fff">扣分:</span><input type="text" class="fill-in"
maxlength="3"
placeholder = "扣除的分数"
name = "deductMarks"
autocomplete="off"
value = "${obj.deductMarks ? obj.deductMarks : ''}"
>
</p>
<p><span style = "color:#fff">评语:</span><input maxlength="30" placeholder="您的评价" autocomplete="off" name = "remark" value = "${obj.remark ? obj.remark : ''}" /></p>
<div class="buttons">
<button οnclick="confirmClick(${obj.myDataLength},${particularTop},${particularLeft})">确定</button>
<button οnclick="cancelClick(${obj.myDataLength})">取消</button>
</div>
</div>`
)
}
审核进行提交
完成上述一系列操作了,我们就可以把结果推送到可视化平台了,部分代码:
// 使用html2canvas进行截图保存
html2canvas($('.banner-bg2'), {
allowTaint: true,
taintTest: false,
onrendered: function (canvas) {
var dataUrl = canvas.toDataURL();
$("#img_pre").attr("src", dataUrl);
}
});
// 前端
function submitUp(){
// 扣分说明
let scoreList = "";
collectArray.forEach((value, index) => {
scoreList +=
`扣分项${index + 1} (扣${value.deductMarks}分) : ${value.remark}。\n`
});
var file=confirmData($('#img_pre').attr('src'));
var data=new FormData();
let authorStr = $('.img-name-two span').text();
let author = authorStr.substring(0,authorStr.length - 4)
data.append("author",author);
data.append("reviewScreenshot",file);
data.append("finalScore",$('.score-num').text() + '分');
data.append("approvedMemo",scoreList);
data.append("filename","t.png");
$.ajax({
url:'http://www.xxxx.com/api/imgGrade',
type: 'post',
data: data,
contentType: false,
// 告诉jQuery不要去设置Content-Type请求头
processData: false,
success: function (data) {
if (data.code == 200) {
$('.popup-post-content').hide()
$('.popup-good').show()
} else {
alert("服务器返回错误!")
}
}
})
}
// node
async function imgGrade(dataList,imgUrl) {
let queryData = {
"appKey":"xxx",
"sign":"xxxx",
"worksheetId":"xxxx",
"controls":
[
// 作者名字
{
"controlId": "author",
"value": dataList.author ? dataList.author : ''
},
// 审核截图
{
"controlId": "reviewScreenshot",
// "value": 'https://www.xxxx.com/guide/image/homePage/banner/imagination-bg.jpg'
"value": imgUrl ? imgUrl : ''
},
// 最终得分
{
"controlId": "finalScore",
"value": dataList.finalScore ? dataList.finalScore : ''
},
// 审核记录
{
"controlId": "approvedMemo",
"value": dataList.approvedMemo ? dataList.approvedMemo : ''
}
]
}
let options = {
method: 'POST',
uri: 'https://api.xxxx.com/v2/open/xxx/xxx',
body: queryData,
json: true
};
try {
var data = await RequestAsync('post', options.uri, { json: options.body });
var result = JSON.parse(data.getBody('utf8'));
if (result.success) {
return {
code: 200
}
} else{
return {
code: 500,
msg: result.error_msg
}
}
} catch (err) {
console.log(err);
return {
code: 500,
msg: error.message
}
}
}
项目负责人查看问题并改正
到此,项目负责人就知道哪有问题,然后就去改正啦!
总结
从小工具的完成到完成文章,这中间已经过去了一年多的时间了,现在想起来这个小工具都很有意思,以后有时间的话会把这个继续完善并且脱敏,做成一个真正的小工具,部署到线上,供各位看官使用。
水平有限,还不能写到尽善尽美,希望大家多多交流,跟春野一同进步!!!