JQ+vue实现图片拼接(无限套娃版)
css样式/* css初始化 */* {margin: 0;padding: 0;}/* 去掉li的小圆点 */li {list-style: none;}/* 去掉a的下划线 */a {text-decoration
·
css样式
/* css初始化 */
* {
margin: 0;
padding: 0;
}
/* 去掉li的小圆点 */
li {
list-style: none;
}
/* 去掉a的下划线 */
a {
text-decoration: none;
}
/* 搜索框去除边框 */
input,
button,
select {
border: 0;
/* 设置背景颜色为透明 */
background-color: transparent;
/* 去掉外轮廓 */
outline: none;
}
/* em和i标签字体样式 */
em,
i {
font-style: normal;
}
/* 图片的空白间隙 */
img {
vertical-align: middle;
}
/* 清除浮动 */
.clearfix:after {
content: '';
display: block;
height: 0;
clear: both;
visibility: hidden;
}
/* 左浮动 */
.fl {
float: left;
}
/* 右浮动 */
.fr {
float: right;
}
body {
background-color: #000;
color: #fff;
}
.lay-box {
display: flex;
}
.lay-left {
flex: 0.5;
margin-top: 2%;
margin-top: 2%;
}
.lay-center {
flex: 2.3;
display: flex;
align-items: center;
justify-content: center;
margin-top: 10%;
position: relative;
flex-direction: column;
min-height: 500px;
}
.lay-center-top {
display: flex;
width: 100%;
height: 100%;
}
.lay-center-bottom {
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
z-index: 1000000;
}
.lay-right {
display: flex;
flex-direction: column;
flex: 0.2;
margin-top: 2%;
z-index: 100000;
}
.automatic,
.manual {
background-color: #22AF90;
text-align: center;
padding: 10px 0px;
border-radius: 5px;
width: 100%;
cursor: pointer;
}
.automatic {
margin-bottom: 20px;
}
.lay-centers {
display: flex;
}
.lay-center-left,
.lay-center-right {
width: 100%;
height: 100%;
}
.lay-center-leftimg,
.lay-center-rightimg {
width: 100%;
height: 100%;
}
.lay-ui {
display: flex;
}
.lay-left-contont .lay-ui .choice {
margin-right: 10px;
}
.choiceclose {
margin-right: 10px;
}
.choiceImg {
width: 30%;
height: 30%;
}
.lay-left-top {
margin-bottom: 20px;
}
/*加载的样式*/
.box {
border-radius: 4px;
height: 20px;
width: 170px;
background: #ebebeb;
position: relative;
}
.box .line {
background: rgb(92, 151, 4);
height: 20px;
text-indent: 999px;
}
.title {
font-size: 18px;
color: #000;
margin-bottom: 20px;
}
.loadding {
position: fixed;
width: 14%;
height: 12%;
background: #fff;
top: 50%;
left: 50%;
margin-top: -6%;
margin-left: -7%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 1000;
}
#canvas {
position: absolute;
display: none;
}
#que,
.clear,
#undo {
background-color: #22AF90;
text-align: center;
padding: 10px 0px;
border-radius: 5px;
width: 10%;
cursor: pointer;
display: none;
}
#imgnewtwo {
display: none;
}
.lay-join-box {
margin-top: 2%;
}
.lay-joint {
display: flex;
margin-top: 1%;
}
.error {
margin-bottom: 50px;
font-size: 18px;
}
html结构
<div class="loadding">
<div class="title">正在拼接中,请稍后...</div>
<div class="box">
<div class="line" data-load="100"></div>
</div>
</div>
<div class="lay-box" id='laybox'>
<div class="lay-left">
<div class="lay-left-contont">
<!--默认展示的图片-->
<div class="lay-ui" v-for="(item,index) in regList" :key='index'>
<input type="checkbox" class="choice" name="img" :data="item.imgurl" @click="specifiName(item.imgurl,item.imgdata)" :uid="item.imgdata">
<img :src="item.imgurl" alt="" class='choiceImg'>
</div>
<!--拼接后的图片-->
<div class='lay-join-box'>
<div class='joint-title'>已拼接</div>
<div class="lay-joint" v-for="(item,index) in jointList" :key='index'>
<input type="checkbox" class="choice" name="img" :value="index" :data="item.imgurl" :uid="item.uid" :oid="item.oid" @click="specifiName(item.imgurl,item.uid)">
<img :src="item.imgurl" alt="" class='choiceImg'>
<button class="error" @click="clean(item.oid,index,item.uid)">×</button>
</div>
</div>
</div>
</div>
<div class="lay-center" id='laycenter'>
<div class='lay-center-top' id="laycentertop">
<canvas id="canvas" ref='canvas' @click="main($event)"></canvas>
<!--手动拼接-->
<div class="lay-centers" id="imgnewone">
<div class="lay-center-left" v-for="item in imgList">
<img :src="item" alt="" class='lay-center-leftimg'>
</div>
</div>
<!--自动拼接-->
<div class="lay-center-left" id="imgnewtwo">
<!--手动拼接展示的图片-->
<img :src="bilgurl" alt="" class='lay-center-leftimg' id="manimg">
<!--自动拼接展示的图片-->
<img :src="bilgurlzi" alt="" class='lay-center-leftimg' id="autoimg">
</div>
</div>
<div class='lay-center-bottom'>
<button id="que" @click="determine">确定</button>
<button class="clear" @click="clear">取消</button>
<button id="undo" :disabled='prohibit' @click="redo">撤销</button>
</div>
</div>
<div class="lay-right">
<button class='automatic' @click="Automatic">自动拼接</button>
<button class='manual' @click="Manual($event)">手动拼接</button>
</div>
</div>
js代码
<script>
$(document).ready(function() {
//全局定义的数组
var newList = []
//全局数组(保存拼接图再拼接的标识)
var prohibit = []
var hid = 0
//自定义的id前缀
var prefix = 'H'
// 加载
var step = 1, //加载基数
status = 100, //加载步骤数
$line = $('.line'),
$lineVal = $line.text(),
$attrVal = $line.data('load'), //进度条属性值
$number = parseInt($('.numb').text()),
$numberVal = parseFloat($number / status); //进度数值
$line.css('width', $lineVal + '%'); //出事进度值
function watchFn() {
var self = $(this);
var showVal = $attrVal / status;
var numberHtml = parseInt($numberVal * step);
//数值小于10让其显示小数点后面一位
if ($number < 10) {
numberHtml = parseFloat($numberVal * step).toFixed(1);
}
//设置进度条、进度数值的样式/内容
$line.css('width', showVal * step + '%');
$('.numb').html(numberHtml);
//基数大于步骤数清空定时器
if (step >= status) {
clearInterval(timer);
}
step += 1;
}
//定时器,每个步骤15毫秒
var timer = setInterval(watchFn, 60);
// vue部分
var app = new Vue({
el: '#laybox',
data: function() {
return {
regList: [], //默认展示的数组
//自动配准的数组
jointList: [], //拼接后的数组
checkboxId: [], //选中的复选框的id
imgList: [],
checkboxList: [], //选中的值
// 配准代码
clicks: 0,
lastClick: [0, 0],
//算法的坐标
coordinateA: [],
coordinateB: [],
// 撤销的数组
undoHistoryA: [],
a: {},
b: {},
prohibit: true,
x: 0,
y: 0,
trigter: true,
//自动配准的计时器
timer: null,
// 手动配准的计时器
timers: null,
//手动的接口图片
bilgurl: '',
//自动的接口图片
bilgurlzi: '',
ash: false, //是否置灰
jointObj: {}, //放置拼接的对象
checkObj: {}, //放置没有
numIndex: null,
}
},
mounted() {
this.regList = JSON.parse(localStorage.getItem("SplicList"))
$('.loadding').hide()
},
methods: {
//自动拼接的数据
specifiName(item, id) {
//自动配准的数组
this.checkboxList.push(item)
this.checkboxId.push(id)
},
//清除
clean(oid, index, uid) {
var res = prohibit.find(item => {
return item == uid
})
if (res == uid) {
alert('无法进行删除')
return false
} else {
//自动拼接
//对应的下标
this.numIndex = index
//取出当前删除的图片oid,并进行对比
var newArr = oid.split('-')
//操作uid
var reelect = $("input[name='img']")
for (var i = 0; i < reelect.length; i++) {
if (reelect[i].checked == true) {
for (var j = 0; j < newArr.length; j++) {
if (reelect[i].getAttribute('uid') == newArr[j]) {
reelect[i].disabled = false
reelect[i].checked = false
}
}
}
}
//删除数组元素
this.jointList.forEach((item, index) => {
if (this.numIndex === index) {
this.jointList.splice(this.numIndex, 1)
}
})
//全局保存的数组赋值
prohibit = prohibit.filter(function(item) {
return item == uid
})
}
//判断是否要清空其他元素
if (this.jointList.length == 0) {
this.bilgurlzi = ''
this.bilgurl = ''
$('#autoimg').hide()
$('#manimg').hide()
}
//手动拼接
},
//自动配准
Automatic() {
$('#imgnewone').hide()
if (this.checkboxList.length < 2) {
alert('请选择两张图片')
return false
} else {
//置灰的判断
var reelect = $("input[name='img']")
for (var i = 0; i < reelect.length; i++) {
if (reelect[i].checked == true) {
reelect[i].disabled = true
}
}
var canvas = document.getElementById("canvas")
context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
$('.loadding').show()
//自动配准接口
var newimg = ''
var newCheck = this.checkboxId
var imgNUm1 = this.checkboxList[0]
var imgNUm2 = this.checkboxList[1]
var imgNUm3 = this.checkboxList[2]
var imgNUm4 = this.checkboxList[3]
var imgNUm5 = this.checkboxList[4]
var imgNUm6 = this.checkboxList[5]
hid++
$.ajax({
type: "GET",
url: "http://www.nb.cn/Remote/Index/imageMosaic",
async: false,
data: {
fisrtImage: imgNUm1,
secondImage: imgNUm2,
thirdImage: imgNUm3,
fourthImage: imgNUm4,
fifthImage: imgNUm5,
sixthImage: imgNUm6
},
success: function(ret) {
newimg = ret.data.fusion_image
newCheck.forEach(item => {
if (item && item.indexOf('H') === 0) {
prohibit.push(item)
}
})
// hid的值 uid
let jointObj = {
imgurl: newimg,
oid: newCheck.join('-'),
uid: prefix + hid,
}
newList.push(jointObj)
setTimeout(() => {
$('.loadding').hide()
$('#manimg').hide()
$('#autoimg').show()
$('#imgnewtwo').show()
}, 800)
},
});
this.jointList = newList
this.checkboxId = []
this.checkboxList = []
this.jointList.forEach((item, index) => {
this.bilgurlzi = this.jointList[index].imgurl
});
}
},
//手动配准
Manual(e) {
$('#imgnewtwo').hide()
if (this.checkboxList.length != 2) {
alert('请选择两张图片')
return false
} else {
$('#que').show()
$('.clear').show()
$('#undo').show()
$('#canvas').show()
this.imgList = this.checkboxList
$('#imgnewone').show()
var canvas = document.querySelector('#canvas')
canvas.width = $('#laycenter').width()
canvas.height = $('#laycenter').height()
}
},
getCursorPosition(e) {
if (e.pageX != undefined && e.pageY != undefined) {
var rect = canvas.getBoundingClientRect();
this.x = e.clientX - rect.left * (canvas.width / rect.width);
this.y = e.clientY - rect.top * (canvas.height / rect.height);
}
return [this.x, this.y];
},
drawLine(e) {
var canvas = document.getElementById("canvas")
context = canvas.getContext('2d');
context.beginPath();
this.x = this.getCursorPosition(e)[0];
this.y = this.getCursorPosition(e)[1];
context.strokeStyle = '#f0f0f0';
if (this.trigter == true) {
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
const compressed = pako.deflate(new Uint8Array(imageData
.data));
this.undoHistoryA.push(compressed);
this.trigter = false
}
context.arc(this.x, this.y, 2, 0, 2 * Math.PI)
context.stroke();
if (this.clicks != 1) {
this.clicks++;
} else {
context.moveTo(this.lastClick[0], this.lastClick[1]);
context.lineTo(this.x, this.y, 6);
context.strokeStyle = '#f0f0f0';
context.stroke();
this.clicks = 0;
}
this.lastClick = [this.x, this.y];
if (this.clicks == 0) {
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
const compressed = pako.deflate(new Uint8Array(imageData
.data));
this.undoHistoryA.push(compressed);
this.prohibit = false
var x = this.x
var y = this.y
this.b = {
x,
y
}
this.coordinateB.push(this.b)
} else {
var x = this.x
var y = this.y
this.a = {
x,
y
}
this.coordinateA.push(this.a)
}
},
main(e) {
var canvas = document.getElementById('canvas')
this.drawLine(e)
},
redo() {
// 撤销
{
this.undoHistoryA.pop();
const compressed = this.undoHistoryA[this.undoHistoryA.length - 1]
this.coordinateA.pop()
this.coordinateB.pop()
try {
const decompressed = pako.inflate(compressed); // 解压
const uint8ClampedArray = new Uint8ClampedArray(decompressed);
const imageData = new ImageData(uint8ClampedArray, canvas.width, canvas
.height);
context.putImageData(imageData, 0, 0);
} catch (error) {
console.error(error);
}
if (this.undoHistoryA.length === 0) {
this.prohibit = true;
}
}
},
determine() {
//置灰的判断
var reelect = $("input[name='img']")
for (var i = 0; i < reelect.length; i++) {
if (reelect[i].checked == true) {
reelect[i].disabled = true
}
}
if (this.coordinateA.length < 4 || this.coordinateB.length < 4) {
alert('最少标注四条线段')
return false
}
var imgNUm1 = this.imgList[0]
var imgNUm2 = this.imgList[1]
var newimg = ''
var newCheck = this.checkboxId
hid++
$('.loadding').show()
$.ajax({
type: "GET",
url: "http://www.nb.cn/Remote/Index/manualSplicing",
async: false,
data: {
fisrtImage: imgNUm1,
secondImage: imgNUm2,
fixedPoint: this.coordinateA,
movedPoint: this.coordinateB
},
success: function(ret) {
newimg = ret.data.fusion_image
newCheck.forEach(item => {
if (item && item.indexOf('H') === 0) {
prohibit.push(item)
}
})
// hid的值 uid
this.jointObj = {
imgurl: newimg,
oid: newCheck.join('-'),
uid: prefix + hid
}
newList.push(this.jointObj)
setTimeout(() => {
$('.loadding').hide()
}, 800)
},
});
// 数组id拼接
this.jointList = newList
this.jointList.forEach((item, index) => {
this.bilgurl = this.jointList[index].imgurl
});
$('#imgnewtwo').show()
$('#imgnewone').hide()
//按钮隐藏
$('#que').hide()
$('.clear').hide()
$('#undo').hide()
$('#canvas').hide()
//图片展示隐藏
$('#manimg').show()
$('#autoimg').hide()
this.checkboxId = []
this.checkboxList = []
context.clearRect(0, 0, canvas.width, canvas.height);
},
clear() {
var canvas = document.getElementById('canvas')
context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
this.imgList = []
$('#que').hide()
$('.clear').hide()
$('#undo').hide()
$('#canvas').hide()
}
}
})
});
</script>
数据可以自行模拟
引入了vue.js jquery.js pako.js
更多推荐
已为社区贡献2条内容
所有评论(0)