| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514 |
- <?php
- // use common\helpers\ComponentHelper;
- // ComponentHelper::loadComponentView('components/style-components/diy-img-setting', __DIR__);
- ?>
- <template id="diy-rubik-cube">
- <div class="diy-rubik-cube">
- <div class="decorate-cube">
- <ul class="cube-col" v-for="(n,nIndex) in densityNum" :key="nIndex">
- <li :class="['cube-item', {'item-selecting': isSelecting(n,i), 'item-selected':isSelected(n,i)}]"
- v-for="(i,iIndex) in densityNum" :key="iIndex+100"
- :style="{'width':cubeCellWidth+'px','height':cubeCellHeight+'px'}"
- :data-x="n" :data-y="i"
- @click="onClickCubeItem($event)"
- @mouseenter="onEnterCubeItem($event)">
- <i class="el-icon-plus" :style="{'line-height':cubeCellHeight+'px'}"></i>
- </li>
- </ul>
- <div class="cube-selected" v-for="(item, index) in selectedList" :key="index + 100"
- :style="{'width':getSelectedWidth(item)+'px','height':getSelectedHeight(item)+'px','top':getSelectedTop(item)+'px','left':getSelectedLeft(item)+'px'}"
- :class="{'click-cube-selected': index == selCubeIndex}"
- @click="selCubeInfo(index)"
- >
- <div class="cube-selected-text" v-if="item.img == ''">
- {{ Math.round(cubeHeight/density*((parseInt(item.end.x) - parseInt(item.start.x) + 1))) }}
- x
- {{ Math.round(cubeWidth/density*((parseInt(item.end.y) - parseInt(item.start.y) + 1))) }}
- 像素
- </div>
- <el-image style="width:100%;height: 100%;" :src="item.img" fit="cover" v-else></el-image>
- <div class="cube-del-icon" @click.stop="delCubeList(index)" v-show="index == selCubeIndex && styleArr.length == 0">
- <i class="el-icon-error del-sel-icon"></i>
- </div>
- </div>
- </div>
- <div :style="{'width':cubeExhibitWidth+'px','height':cubeExhibitHeight+'px'}"></div>
- <diy-img-setting
- v-show="selCubeIndex != -1"
- :img-infos="cubeImgInfo"
- def-img-count="1"
- :suggest-site="99"
- suggest-size-text=""
- :img-contain-style="{padding: 0,'margin-top': '20px'}"
- :show-title="false"
- @change="addCubeImg"
- ></diy-img-setting>
- </div>
- </template>
- <script>
- Vue.component('diy-rubik-cube', {
- template: '#diy-rubik-cube',
- name: 'diy-rubik-cube',
- props: {
- density: {//密度
- type: [String,Number],
- default: 4
- },
- cubeWidth: { //魔方宽度
- type: [String,Number],
- default: 750
- },
- cubeHeight: { //魔方高度
- type: [String,Number],
- default: 750
- },
- cubeExhibitWidth: { //魔方展示宽度。
- type: [String,Number],
- default: 320
- },
- cubeExhibitHeight: { //魔方展示宽度。
- type: [String,Number],
- default: 320
- },
- cubeList: { //魔方数据
- type: Array,
- default: () => {
- return [];
- }
- },
- styleArr: { //风格样式
- type: Array,
- default: () => {
- return [];
- }
- },
- styleBoo: { //用于装修切回去数据丢失问题
- type: Boolean,
- default: false,
- }
-
- },
- data() {
- return {
- selectingItem: {
- 'tempStart': null,
- 'tempEnd': null,
- 'start': null,
- 'end': null
- },
- selectedList: [], //已经生成的单元。
- selCubeIndex: -1,
- addGridArr: [], // 保存每个选中的格子
- cubeImgInfo: [], //图片信息
- maxHeight: 0,//魔方以选中的最高高度
- }
- },
- watch: {
- cubeList: {
- deep:true,
- immediate: true,
- handler(val) {
- this.selectedList = val;
- this.addGridArr = [];
- let that = this;
- this.selectedList.forEach(v => {
- let gridData = that.getGridSeat(v.start,v.end);
- that.addGridArr.push(...gridData);
- })
- }
- },
- styleArr: {
- deep:true,
- immediate: true,
- handler(val) {
- if(!val.length) return;
- let that = this;
- this.addGridArr = [];
- let newList = [];
- val.forEach(v => {
- let gridData = this.getGridSeat(v.start,v.end);
- let dataObj = {
- 'start': v.start,
- 'end': v.end,
- 'img': '',
- 'url': '',
- 'originalData': [],// 图片组件传过来的数据
- }
-
- // +判断是否为切回来的
- if(this.selectedList.length > 0 && this.styleBoo){
- let dataIndex = this.selectedList.findIndex(listVal => listVal.start.x == v.start.x && listVal.start.y == v.start.y && listVal.end.x == v.end.x && listVal.end.y == v.end.y);
- if(dataIndex != -1){
- dataObj = this.selectedList[dataIndex];
- }
- console.info(dataIndex);
- }
- let style = that.getCubeStyle(v.start,v.end);
- that.$set(dataObj,"style",style);
- that.addGridArr.push(...gridData);
- newList.push(dataObj);
- })
- this.selCubeIndex = -1;
- this.cubeImgInfo = [];
- this.selectedList = newList;
- this.getCubeMaxHeight();
- this.updateData();
- }
- }
- },
- computed: {
- //密度值。
- densityNum: function () {
- return parseInt(this.density);
- },
- //单元魔方高度。
- cubeCellHeight: function () {
- return this.cubeExhibitHeight / this.density;
- },
- //单元魔方宽度。
- cubeCellWidth: function () {
- return this.cubeExhibitWidth / this.density;
- },
- },
- methods: {
- //获取开始和结束之间的所有魔方单元。
- updateSelecting() {
- var tempStart = this.selectingItem.tempStart;
- var tempEnd = this.selectingItem.tempEnd;
- this.selectingItem.start = {
- x: Math.min(tempStart.x, tempEnd.x),
- y: Math.min(tempStart.y, tempEnd.y)
- };
- this.selectingItem.end = {
- x: Math.max(tempStart.x, tempEnd.x),
- y: Math.max(tempStart.y, tempEnd.y)
- };
- },
- //清除正在选择的。
- clearSelecting() {
- this.selectingItem.tempStart = null;
- this.selectingItem.tempEnd = null;
- this.selectingItem.start = null;
- this.selectingItem.end = null;
- },
- // 获取鼠标移动的位置
- coordFromCubeEvent(event) {
- var el = event.currentTarget;
- var x = el.getAttribute('data-x');
- var y = el.getAttribute('data-y');
- // console.log('track_x_y_[' + x + ', ' + y + ']');
- return { x: x, y: y };
- },
- isContain(x, y, item) {
- return (item.start.x <= x && x <= item.end.x && item.start.y <= y && y <= item.end.y);
- },
- //魔方点击事件。
- onClickCubeItem: function (event) {
- var domclass = event.currentTarget.getAttribute('class');
- console.info(domclass);
- if (-1 !== domclass.indexOf('item-selected')) {
- console.log("已经被占用");
- return;
- }
- var coord = this.coordFromCubeEvent(event);
- // 开始点击
- if (null == this.selectingItem.tempStart) {
- this.selectingItem.tempStart = coord;
- this.selectingItem.tempEnd = coord;
- this.selectingItem.start = coord;
- this.selectingItem.end = coord;
- return;
- }
- this.selectingItem.tempEnd = coord;
- this.updateSelecting();
-
- // 添加以选中的格子
- let gridData = this.getGridSeat(this.selectingItem.start,this.selectingItem.end);
- // 用于判断格子是否被选中
- let boo = this.verifyGridExist(this.selectingItem.start,this.selectingItem.end);
-
- if(boo){
- return;
- }
- this.addGridArr.push(...gridData);
- this.getCubeMaxHeight();
- //加入选中的。
- var selectedItem = {
- 'start': this.selectingItem.start,
- 'end': this.selectingItem.end,
- 'img': '',
- 'url': '',
- 'originalData': [],// 图片组件传过来的数据
- }
- //计算选中层的宽度。
- let style = this.getCubeStyle(selectedItem.start,selectedItem.end);
- this.$set(selectedItem,"style",style);
- this.selectedList.push(selectedItem);
- this.selCubeInfo(this.selectedList.length - 1);
- // 清楚状态
- this.clearSelecting();
- this.updateData();
- },
- // 获取每个各种的位置 type: 1 添加 2:删除
- getGridSeat(start,end,type=1){
- let gridData = [];
- // 添加以选中的格子
- console.info(this.selectingItem);
- for(let i = start.x;i<=end.x;i++){
- let arr = [];
- for(let j = start.y;j<=end.y;j++){
- arr.push({
- x: i,
- y: j
- })
- }
- if(type == 1){
- gridData.push(...arr);
- } else {
- arr.forEach(val => {
- let startIndex = this.addGridArr.findIndex(v => (v.x == val.x && v.y == val.y));
- if(startIndex != -1){
- this.addGridArr.splice(startIndex,1)
- }
- })
- this.getCubeMaxHeight();
- }
- }
- return gridData;
- },
- // 判断是否在已选中的范围中
- verifyGridExist(start,end){
- let gridData = this.getGridSeat(start,end);
- // 用于判断格子是否被选中
- let mergeArr = [...this.addGridArr];
- mergeArr.push(...gridData);
- let delRepeatArr = [];
- let repeatCount = 0;
- mergeArr.forEach(function(a) {
- let boo = delRepeatArr.every(function(b) {
- return a.x != b.x || a.y != b.y;
- })
- boo ? delRepeatArr.push(a) : repeatCount++;
- })
-
- if(repeatCount > 0){
- this.$message.error('该位置无法选择');
- return true;
- }
- return false;
- },
- // 计算魔方已选中的最高高度
- getCubeMaxHeight(){
- let size = this.cubeWidth/this.density; //每个格子的大小
- let maxHeight = 0;
- let maxY = 0;
- for(let i = 1;i<=this.density;i++){
- let yInfo = this.addGridArr.filter(v => v.y == i);
- if(yInfo.length){
- let y = yInfo[yInfo.length -1].y;
- y>maxY?maxY = y:'';
- }
- }
- maxHeight = maxY * size;
- this.maxHeight = maxHeight;
- this.$emit("max",this.maxHeight);
- },
- // 计算魔方样式
- getCubeStyle(start,end){
- //计算选中层的宽度。
- let infoWidth = Math.round(this.cubeHeight/this.density*((parseInt(end.x) - parseInt(start.x) + 1)));
- let infoHeight = Math.round(this.cubeWidth/this.density*((parseInt(end.y) - parseInt(start.y) + 1)));
- let infoTop = Math.round(this.cubeWidth/this.density*((start.y - 1) ));
- let infoLeft = Math.round(this.cubeWidth/this.density*((start.x - 1)));
-
- let style = {
- top: (infoTop/2) + 'px',
- left: (infoLeft/2) + 'px',
- width: (infoWidth/2) + 'px',
- height: (infoHeight/2) + 'px',
- }
- return style;
- },
- // 鼠标移动触发
- onEnterCubeItem: function (event) {
- // console.log("track_onEnterCube");
- if (this.selectingItem.tempStart) {
- var coord = this.coordFromCubeEvent(event);
- this.selectingItem.tempEnd = coord;
- // console.info(this.selectingItem.tempEnd);
- this.updateSelecting();
- }
- },
- //判断是否正在选择
- isSelecting: function (x, y) {
- var item = this.selectingItem;
- if (item.tempStart) {
- return this.isContain(x, y, item);
- }
- return false;
- },
- //判断是否已经选择。
- isSelected: function (x, y) {
- var list = this.selectedList;
- for (var i = 0; i < list.length; i++) {
- if (this.isContain(x, y, list[i])) {
- return true;
- }
- }
- return false;
- },
- // 选中
- selCubeInfo(index){
- this.selCubeIndex = index;
- if(this.selectedList[this.selCubeIndex]){
- this.cubeImgInfo = this.selectedList[this.selCubeIndex].originalData;
- }
-
- },
- // 删除
- delCubeList(index){
- this.getGridSeat(this.selectedList[index].start,this.selectedList[index].end,2);
- this.selectedList.splice(index, 1);
- if(index == this.selCubeIndex){
- this.selCubeInfo(this.selCubeIndex-1);
- }
- this.updateData();
- },
- // 通信
- updateData(){
- this.$emit("chang",this.selectedList)
- },
- // 添加图片
- addCubeImg(imgArr){
- console.info(this.selCubeIndex,"0",this.selectedList);
- if(this.selCubeIndex != -1){
- this.selectedList[this.selCubeIndex].img = imgArr[0].imgUrl;
- this.selectedList[this.selCubeIndex].url = imgArr[0].url;
- this.selectedList[this.selCubeIndex].originalData = imgArr;
- }
- this.updateData();
- },
- //计算选中层的宽度。
- getSelectedWidth: function (item) {
- return (parseInt(item.end.x) - parseInt(item.start.x) + 1) * this.cubeCellWidth;
- },
- //计算选中层的高度。
- getSelectedHeight: function (item) {
- return (parseInt(item.end.y) - parseInt(item.start.y) + 1) * this.cubeCellHeight;
- },
- //计算选中层的右边距离。
- getSelectedTop: function (item) {
- return (item.start.y - 1) * this.cubeCellHeight;
- },
- //计算选中层的左边距离。
- getSelectedLeft: function (item) {
- return (item.start.x - 1) * this.cubeCellWidth;
- }
- }
- })
- </script>
- <style>
- .diy-rubik-cube{
- display: inline-block;
- width: 100%;
- }
-
- .decorate-cube {
- position: relative;
- }
- .decorate-cube .cube-item {
- border-right: 1px solid #B7B7B7;
- }
- .decorate-cube .cube-selected {
- position: absolute;
- background-color: #E8F7FD;
- border: 1px solid #BBDDFF;
- text-align: center;
- color: #88C4DC;
- cursor: pointer;
- box-sizing: border-box;
- }
- .decorate-cube .click-cube-selected{
- border: 1px solid #3388FF;
- }
- /* .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: 12px;
- width: 100%;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translateX(-50%) translateY(-50%);
- }
- .decorate-cube .cube-col {
- float: left;
- list-style: none;
- padding: 0;
- margin: 0;
- }
- .decorate-cube .cube-item:first-child {
- border-top: 1px solid #B7B7B7;
- }
- .decorate-cube .cube-item {
- background: #FFF;
- border-left: 1px solid #B7B7B7;
- border-bottom: 1px solid #B7B7B7;
- cursor: pointer;
- text-align: center;
- box-sizing: border-box;
- }
- .decorate-cube .cube-item.item-selecting {
- background: #e0edff;
- }
- .decorate-cube .cube-item.item-selected {
- background: #e0edff;
- visibility: hidden;
- }
- .cube-del-icon{
- position: absolute;
- right: -8px;
- top: -8px;
- z-index: 10;
- }
- .del-sel-icon{
- font-size: 19px;
- color: #666;
- background: #FFF;
- border-radius: 50%;
- }
-
- </style>
|