vue仿有赞 魔方插件 源码分享
项目要求封装一个有赞魔方矩阵类型的插件,我当时内心是拒绝的费尽周折查阅很多资料才找到靠谱的方法,下图为效果,因为没有几行代码就直接在csdn上分享了解决思路为:1、一共两层底下层添加自定义属性 y x 确定每一块元素的几行几列;2、知道点击的是几行几列之后计算出单个单元格的宽,上层通过定位实现;记得在确定的时候做个判断 当前选中是否和其他冲突上代码<template><div c
·
项目要求封装一个有赞魔方矩阵类型的插件,我当时内心是拒绝的
费尽周折查阅很多资料才找到靠谱的方法,下图为效果,因为没有几行代码就直接在csdn上分享了
解决思路为:
1、一共两层底下层添加自定义属性 y x 确定每一块元素的几行几列;
2、知道点击的是几行几列之后计算出单个单元格的宽,上层通过定位实现;
记得在确定的时候做个判断 当前选中是否和其他冲突
上代码
<template>
<div class="rowncolnParam">
<div class="decorate-cube" style="margin-left:50px;">
<ul class="cube-row" v-for="n in densityNum" :key="'ulrow'+n">
<li
:class="['cube-item',{'item-selecting': isSelecting(i,n),'item-selected':isSelected(i,n) }]"
v-for="i in densityNum" :key="'licol'+i"
:data-x="i" :data-y="n"
:style="{'width':cubeItemWidth+'px','height':cubeItemHeight+'px'}"
@click="cubeItemClick($event)">
</li>
</ul>
<div class="cube-selected"
v-for="(item, index) in data.cudeSelected" :key="index"
:style="{'width':getCubeSelectedWidth(item)+'px','height':getCubeSelectedHeight(item)+'px','top':getCubeSelectedTop(item)+'px','left':getCubeSelectedLeft(item)+'px'}"
>
<p @click="cubeSelectedDel(index)" class="cube-selected-del">x</p>
<img :src="item.src" alt="" v-if="item.src" @click="addBanner(index)">
<div class="cube-selected-text" v-else @click="addBanner(index)">
<div>
<i class="el-icon-circle-plus-outline"></i>
<!-- 像素计算方式保留方便使用 {{ Math.round(cubeWidth/densityNum*((parseInt(item.end.y) - parseInt(item.start.y) + 1))) }} x
{{ Math.round(cubeHeight/densityNum*((parseInt(item.end.x) - parseInt(item.start.x) + 1))) }} 像素 -->
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import upload from '@/components/fitmentparam/upload.vue'
export default {
components:{upload},
props:{
data:{
type:Object,
default:""
}
},
data(){
return{
'cubeWidth':300, //魔方宽度
'cubeHeight':300, //魔方高度
'cudeSelecting':{
'start':null,
'end':null,
'data':[]
},
// 'cudeSelected':[] //已经生成的单元
}
},
created(){
console.log(this.data,"数据")
},
computed:{
//密度值 几×几
densityNum () {
return 7;
},
//单元魔方高度
cubeItemHeight:function () {
return this.cubeWidth/this.densityNum;
},
//单元魔方宽度
cubeItemWidth:function () {
return this.cubeWidth/this.densityNum;
},
},
methods:{
//魔方点击事件
cubeItemClick(event) {
var el = event.currentTarget;
var x = el.getAttribute('data-x');
var y = el.getAttribute('data-y');
var domclass = el.getAttribute('class');
console.log('['+x+','+y+','+domclass+']执行了点击');
var cudeSelectingStart = this.cudeSelecting.start;
var coord = {x:x,y:y};
if(-1 !== domclass.indexOf('item-selected')){
alert("已经被占用");
return;
}
if(null == cudeSelectingStart){
this.cudeSelecting.start = coord;
this.cudeSelecting.data.push(coord);
}else{
this.cudeSelecting.end = coord;
this.cudeSelecting.data.push(coord);
//获取开始和结束之间所有魔方单元
var start = cudeSelectingStart;
var end = coord;
var x_start = Math.min(start.x,end.x);
var x_end = Math.max(start.x,end.x);
var y_start = Math.min(start.y,end.y);
var y_end = Math.max(start.y,end.y);
var real_start = {x:Math.min(start.x,end.x),y:Math.min(start.y,end.y)};
var real_end = {x:Math.max(start.x,end.x),y:Math.max(start.y,end.y)};
//找到所有选择范围内的
this.cudeSelecting.data.splice(0);
for(var i=x_start;i<=x_end;i++){
for(var j=y_start;j<=y_end;j++){
this.cudeSelecting.data.push({x:i,y:j});
}
}
var cudeSelectingData = this.cudeSelecting.data;
var cudeSelectedArr = [];
for(var i=0;i<cudeSelectingData.length;i++){
cudeSelectedArr.push(cudeSelectingData[i])
}
console.log(cudeSelectedArr);
console.log(real_start);
console.log(real_end);
//加入选中的
var cudeSelected = {
'start':real_start,
'end':real_end,
'data':cudeSelectedArr
}
this.data.cudeSelected.push(cudeSelected);
console.log("合并完成数据",this.data.cudeSelected)
//清除正在选择的
this.cudeSelecting.start = null;
this.cudeSelecting.end = null;
this.cudeSelecting.data.splice(0);
}
},
//判断是否正在选择
isSelecting:function (x,y) {
var cudeSelectingData = this.cudeSelecting.data;
for(var i = 0, len = cudeSelectingData.length; i < len; i++){
var coord = cudeSelectingData[i];
if(parseInt(coord.x) === parseInt(x) && parseInt(coord.y) === parseInt(y)){
return true;
}
}
return false;
},
//判断是否已经选择
isSelected:function (x,y) {
var list = this.data.cudeSelected;
for(var i=0;i<list.length;i++){
var data = list[i].data;
for(var j=0;j<data.length;j++){
var coord = data[j];
if(parseInt(coord.x) === parseInt(x) && parseInt(coord.y) === parseInt(y)){
return true;
}
}
}
return false;
},
// 删除并分解当前模块
cubeSelectedDel(index){
this.$confirm('确认删除?')
.then(_ => {
this.data.cudeSelected.splice(index,1);
})
.catch(_ => {});
},
//计算选中层的宽度
getCubeSelectedWidth:function (item) {
return (parseInt(item.end.y) - parseInt(item.start.y) + 1) * this.cubeItemWidth;
},
//计算选中层的高度
getCubeSelectedHeight:function (item) {
return (parseInt(item.end.x) - parseInt(item.start.x) + 1) * this.cubeItemHeight;
},
//计算选中层的右边距离
getCubeSelectedTop:function (item) {
return (item.start.x-1) * this.cubeItemHeight;
},
//计算选中层的左边距离
getCubeSelectedLeft:function (item) {
return (item.start.y-1) * this.cubeItemWidth;
},
}
}
</script>
<style lang="scss">
.rowncolnParam {
// text-align: center;
h4 {
color: #444;
}
}
.decorate-cube {
width: 375px;
height: 375px;
position: relative;
}
.decorate-cube .cube-row:last-of-type .cube-item {
border-right: 1px solid #e5e5e5;
}
.decorate-cube .cube-selected {
position: absolute;
background-color: #fff;
border: 1px solid #ebedf0;
text-align: center;
color: #7d7e80;
cursor: pointer;
box-sizing: border-box;
overflow: hidden;
}
// 添加的图片
.cube-selected img{
width: 100%;
}
.decorate-cube .cube-selected.cube-selected-click {
background: #e0edff;
border: 1px solid #155bd4;
color: #155bd4;
z-index: 2;
cursor: auto;
}
.decorate-cube .cube-selected-text {
font-size: 20px;
width: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
// 删除
.cube-selected-del{
text-align: center;
width: 12px;
height: 12px;
color: #f3704b;
line-height: 9px;
font-size: 2px;
border-radius: 50%;
border: 0.5px solid #f3704b;
position: absolute;
top: 0px;
right: 5px;
display: none;
}
.cube-selected:hover .cube-selected-del{
display: block;
}
.decorate-cube .cube-row {
float: left;
list-style: none;
padding: 0;
margin: 0;
}
.decorate-cube .cube-item:first-child {
border-top: 1px solid #e5e5e5;
}
.decorate-cube .cube-item {
background: #f8f8f8;
border-left: 1px solid #e5e5e5;
border-bottom: 1px solid #e5e5e5;
cursor: pointer;
text-align: center;
box-sizing: border-box;
}
.decorate-cube .cube-item.item-selecting {
background: #e0edff;
}
.decorate-cube .cube-item.item-selecting .van-icon {
display: none;
}
.decorate-cube .cube-item.item-selected {
background: #e0edff;
visibility: hidden;
}
.decorate-cube .cube-item.item-selected .van-icon {
display: none;
}
</style>
上述资料是多人分享出的基础上更改的
其他小插件后续我会打包分享出来的,有问题的朋友也可私信我
更多推荐
已为社区贡献4条内容
所有评论(0)