原文链接 juejin.cn/post/734695…
博主是用 react 写的,小编借鉴博主的思路实现了vue的,源码在最后,没有进行太多的封装,至于为什么呢,大家都懂 代码实现细节请关注源码注释
背景:多元化的炫酷商城首页,C段用户各不相同的需求,魔方组件的多样化布局和自定义链接应运而生。
效果
功能特点
-
多样化的布局选择
-
固定宽满屏<750rpx>,高等比例<750rpx>
-
布局选择
- 预定义10种布局
- 风格11 自定义模板支持鼠标选定布局大小,范围切换动态调整选中块大小,支持 4 => 7(行*列)
-
-
支持上传商品图片或者其他宣传海报,并配置相关链接
- 可调整图片间隙和尺寸要求,适配不同的布局需求
思路预演<直角坐标系辅佐,左上角为原点,以横轴最大等分块为1单位>
- 风格1上下各一个,风格2左右各一个,以坐标系为例,将坐标系等分为4个全等的依次排列的正方形,风格一就可等价为宽为2,高为1,纵轴排列的两个长方形,同理,风格2就是横轴排列的两个宽为1,高为2的长方形
- 以此,风格八就是等分的四个块以此排列
- 风格三就是等分的9块,横轴排列的宽为1,高为3的长方形
- 风格4-7,就是等分的四块进行各方向排列
- 这样一来,等分块进行分割坐标系之后,是不是就是很简单啦
数据格式
// 风格一到风格十通用;风格十一也一样,主要是风格十一有一个用户选择和防重复校验的问题。
magic_1: {
// 以横轴最大等分块
diyCubeNumber: 2,
// 块数据
diyCubeResult: [{ // 最小单元格数据,风格通用
x: 0, // 横轴坐标点
y: 0, // 纵轴坐标点
height: 1, // 上文思路所讲述的高度
width: 2, // 上文思路所讲述的宽度
url: '', // 该设定单元格所绑定的适用图片链接
link: '', // 该设定单元格所绑定的适用跳转链接(移动端是 uniapp 开发的小程序)
linkname: '' // 该设定单元格所绑定的适用跳转链接名称
}, {
x: 0,
y: 1,
height: 1,
width: 2,
url: '',
link: '',
linkname: ''
}]
}
风格十一实现思路
总结:两层dom重叠,底层正常排列进行选取,上层利用单元格单位长度进行定位
主要代码
<div class="right-setting-box-item magic-box" @mouseleave="handleMouseLeave"
:style="{width: itemWidth * item.diyCubeNumber +'px', height: itemWidth * item.diyCubeNumber +'px'}">
<template v-if="item.comp_style == 11">
<!-- 默认画板数据 -->
<div class="defaule-row" v-for="(item,index) in diyCubeData" :key="index">
<div class="defaule-col" :class="{'item-seleting': currentCubeKey.includes(mergeKey(index, index2))}"
:style="{width: itemWidth * item2.width +'px',height: itemWidth * item2.height+'px'}"
v-for="(item2 ,index2) in item" :key="index2" @click="handleDefaultMagic(item2)"
@mouseover.stop="mouseoverDefaultMagic(item2)">
<i class="iconfont ttdiy-add"></i>
</div>
</div>
</template>
<!-- 选中定位的画板 -->
<template v-if="item.diyCubeResult.length">
<div class="diy-magic-item" v-for="(it,idx) in item.diyCubeResult" :key="idx+100" :style="getStyle(it)"
:class="{'active': idx == currentCubeIndex}" @click="clickDiyMagic(idx)">
<i class="el-icon-error" @click.stop="removeDiyMagic(idx)"></i>
<img v-if="it.url" :src="it.url">
<span v-else>{{ `${Math.floor(it.width * itemWidth)} * ${Math.floor(it.height * itemWidth)}` }}</span>
</div>
</template>
</div>
<script>
export default{
data(){
return{
// 容器的最大宽度
maxBoxWidth: 375,
}
},
computed: {
// 计算每个单元格的宽度
itemWidth() {
return this.maxBoxWidth / this.item.diyCubeNumber
}
},
methods: {
getStyle(item) {
const { x, y, width, height } = item;
let style = {
left: `${x * this.itemWidth}px`,
top: `${y * this.itemWidth}px`,
width: `${width * this.itemWidth}px`,
height: `${height * this.itemWidth}px`
}
return style
}
}
}
</script>
重点关注 底层的默认画板数据和已选中的数据
clickDiyMagic 这个方法,主要是操作已生成的块进行绑定数据
handleDefaultMagic 这个方法,用户开始操作选中
mouseoverDefaultMagic 这个方法,主要处理用户操作鼠标移动的时候,其余块是否可选,核心判定也在这个方法里面,卖个关子
整个魔方的难重点
矩形重叠的判定(图片借用)
在鼠标移动过程中,如果当前选择块和已经存在的块重叠,就不做处理,所以就要把选择块和已存在块进行校验处理
// 魔方默认块的移入事件
mouseoverDefaultMagic(item2) {
// console.log(item2);
// 如果当前不是编辑状态,则直接返回
if (!this.cubeEdit) return
// 定义一个空数组,用于存储当前魔方块的key
const keys = [];
// 取出当前魔方块的首位数据
const start = this.untieKey(this.currentCubeStartKey)
// 取出当前魔方块的结尾数据
const end = { ...item2 }
// 处理魔方块的y和x,从小到大,方便后续计算、追加数据
const ys = [start.y, end.y].sort()
const xs = [start.x, end.x].sort()
// 判定是否重叠
if (this.antiCollision(start, end)) {
return;
}
for (let i = ys[0]; i <= ys[1]; i++) {
for (let j = xs[0]; j <= xs[1]; j++) {
keys.push(this.mergeKey(i, j))
}
}
this.currentCubeKey = keys
},
antiCollision(start, end) {
// 有可能从右边从左边选,导致 start.x > end.y,所以要排序
// 保证 rec1 [x1,y1,x2,y2] (x1,y1)为左上角坐标,(x2,y2)为右下角坐标
const xs = [start.x, end.x].sort();
const ys = [start.y, end.y].sort();
// 因为 end 记录的是 li 块的左上角坐标,构成矩形区域的话,应该算 li 块右下角坐标,所以 + 1
const rec1 = [xs[0], ys[0], xs[1] + 1, ys[1] + 1]
// console.log(rec1, 'rec1');
for (let i = 0; i < this.item.diyCubeResult.length; i++) {
const item = this.item.diyCubeResult[i];
const rec2 = [item.x, item.y, item.x + item.width, item.y + item.height]
// console.log(rec2, 'rec2');
const isIntersect = this.isIntersect(rec1, rec2);
if (isIntersect) return true
}
return false
},
// 核心判定两个矩形是否重叠
isIntersect(rec1, rec2) {
/**
* 核心
* 思想:两矩形右边界的最小值大于两矩形左边界的最大值,说明横轴两重叠,两矩形下边界的最小值大于两矩形上边界的最大值,说明纵轴两重叠,两者必须为真
*/
return (Math.min(rec1[2], rec2[2]) > Math.max(rec1[0], rec2[0]) &&
Math.min(rec1[3], rec2[3]) > Math.max(rec1[1], rec2[1]));
},
以上对于魔方的思路讲解就到这里,是不是很简单
源码
源码是跟项目走的,自行摘取 自定义魔方相关逻辑
项目是 vue2 + element UI 实现的
// 右侧的配置板块
<template>
<div class="right-title-box magic-cube">
<div class="right-componet-name">
<img :src="require(`@/assets/decoration/images/${idToIconMap[item.comp_id].icon}`)" />
<span>{{ idToIconMap[item.comp_id].label }}</span>
</div>
<div class="right-cat-line"></div>
<div class="right-setting-box">
<div class="right-setting-box-title">选择风格</div>
<div class="right-setting-box-item">
<el-button type="primary" size="small" @click="openStyleDialog">选择风格</el-button>
<span style="margin-left: 16px">当前:风格{{ item.comp_style }}</span>
</div>
</div>
<div class="right-cat-line"></div>
<div class="right-setting-box">
<div class="right-setting-box-title">魔方布局</div>
<div class="right-setting-box-item" v-if="item.comp_style == 11">
<div class="label">魔方密度</div>
<el-select v-model="item.diyCubeNumber" @change="handleNumberChange">
<el-option v-for="it in diyCubeNumberEnum" :key="it.value" :label="it.label" :value="it.value"></el-option>
</el-select>
</div>
<div class="right-setting-box-item magic-box" @mouseleave="handleMouseLeave"
:style="{width: itemWidth * item.diyCubeNumber +'px', height: itemWidth * item.diyCubeNumber +'px'}">
<template v-if="item.comp_style == 11">
<!-- 默认画板数据 -->
<div class="defaule-row" v-for="(item,index) in diyCubeData" :key="index">
<div class="defaule-col" :class="{'item-seleting': currentCubeKey.includes(mergeKey(index, index2))}"
:style="{width: itemWidth * item2.width +'px',height: itemWidth * item2.height+'px'}"
v-for="(item2 ,index2) in item" :key="index2" @click="handleDefaultMagic(item2)"
@mouseover.stop="mouseoverDefaultMagic(item2)">
<i class="iconfont ttdiy-add"></i>
</div>
</div>
</template>
<!-- 选中定位的画板 -->
<template v-if="item.diyCubeResult.length">
<div class="diy-magic-item" v-for="(it,idx) in item.diyCubeResult" :key="idx+100" :style="getStyle(it)"
:class="{'active': idx == currentCubeIndex}" @click="clickDiyMagic(idx)">
<i class="el-icon-error" @click.stop="removeDiyMagic(idx)"></i>
<img v-if="it.url" :src="it.url">
<span v-else>{{ `${Math.floor(it.width * itemWidth)} * ${Math.floor(it.height * itemWidth)}` }}</span>
</div>
</template>
</div>
<template v-if="item.diyCubeResult.length">
<div class="right-setting-box-title">数据</div>
<div class="right-setting-box-item" style="padding-left: 10px;">
<ImgPicker :image_obj="item.diyCubeResult[currentCubeIndex]" image_key="url"></ImgPicker>
</div>
<div class="right-setting-box-item" style="padding-left: 10px;">
<LinkPicker :linkobj="item.diyCubeResult[currentCubeIndex]" link_key="link" linkname_key="linkname">
</LinkPicker>
</div>
</template>
</div>
<div class="right-cat-line"></div>
<div class="right-setting-box">
<div class="right-setting-box-title">背景设置</div>
<div class="right-setting-box-item">
<div class="label">底部背景</div>
<ColorPicker :color_obj="item" color_key="comp_bg"></ColorPicker>
</div>
</div>
<div class="right-cat-line"></div>
<div class="right-setting-box">
<div class="right-setting-box-title">边距设置</div>
<div class="right-setting-box-item">
<div class="label">图片间距</div>
<SliderPicker :slider_obj="item" slider_key="image_space" :min="0" :max="20" append="px"></SliderPicker>
</div>
<div class="right-setting-box-item">
<div class="label">上边距</div>
<SliderPicker :slider_obj="item" slider_key="padding_top" :min="0" :max="50" append="px"></SliderPicker>
</div>
<div class="right-setting-box-item">
<div class="label">下边距</div>
<SliderPicker :slider_obj="item" slider_key="padding_bottom" :min="0" :max="50" append="px"></SliderPicker>
</div>
<div class="right-setting-box-item">
<div class="label">左右边距</div>
<SliderPicker :slider_obj="item" slider_key="padding_left_right" :min="0" :max="20" append="px"></SliderPicker>
</div>
</div>
<div class="right-cat-line"></div>
<div class="right-setting-box">
<div class="right-setting-box-title">圆角设置</div>
<div class="right-setting-box-item">
<div class="label">上圆角</div>
<SliderPicker :slider_obj="item" slider_key="top_radius" :min="0" :max="20" append="px"></SliderPicker>
</div>
<div class="right-setting-box-item">
<div class="label">下圆角</div>
<SliderPicker :slider_obj="item" slider_key="bottom_radius" :min="0" :max="20" append="px"></SliderPicker>
</div>
</div>
<!-- 风格选择 -->
<el-dialog title="风格选择器" :visible.sync="styleDialogVisible" width="50%">
<div class="dialog-box">
<div class="img-item-box" v-for="it in 11" :key="it">
<div class="img-item" :class="{ active: styleDialogValue == it }" @click="styleDialogValue = it">
<img :src="require(`@/assets/decoration/images/cube/cube${it}.svg`)" />
</div>
<span>风格{{ it }}</span>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="styleDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="closeStyleDialog">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
// 默认布局,用于风格切换
import magic_default from '../../js/magic_default'
import { idToIconMap } from "../../js/left_menu";
const ImgPicker = () => import("../ImgPicker.vue");
const SliderPicker = () => import("../SliderPicker.vue");
const ColorPicker = () => import("../ColorPicker.vue");
const LinkPicker = () => import("../LinkPicker.vue");
export default {
data() {
return {
idToIconMap,
// 定义最小单元格数据模板
cube: {
"x": 0, // 小块的横向位置
"y": 0, // 小块的纵向位置
"height": 1, // 小块的宽度占比
"width": 1, // 小块的高度占比
},
diyCubeNumberEnum: [{
value: 4,
label: '4 * 4'
}, {
value: 5,
label: '5 * 5'
}, {
value: 6,
label: '6 * 6'
}, {
value: 7,
label: '7 * 7'
}],
// 魔方数据
diyCubeData: [],
// 容器的最大宽度
maxBoxWidth: 375,
// 当前单元块是否在编辑
cubeEdit: false,
// 当前编辑的key数组
currentCubeKey: [],
// 开始编辑的key
currentCubeStartKey: '',
// 操作生成的魔方数据选中下标
currentCubeIndex: 0,
// 魔方样式弹窗
styleDialogVisible: false,
styleDialogValue: 1
}
},
props: ['item'],
components: {
ImgPicker,
SliderPicker,
ColorPicker,
LinkPicker
},
created() {
this.init()
},
computed: {
// 计算每个单元格的宽度
itemWidth() {
return this.maxBoxWidth / this.item.diyCubeNumber
}
},
methods: {
openStyleDialog() {
this.styleDialogValue = this.item.comp_style;
this.styleDialogVisible = true;
},
closeStyleDialog() {
this.item.comp_style = this.styleDialogValue;
// 切换风格注意切换默认值
this.currentCubeIndex = 0;
if (this.styleDialogValue == 11) {
this.item.diyCubeNumber = 4;
this.item.diyCubeResult = [];
this.styleDialogVisible = false;
this.initDefault()
} else {
const _traght = 'magic_' + this.styleDialogValue;
const _value = JSON.parse(JSON.stringify(magic_default[_traght]));
this.item.diyCubeNumber = _value.diyCubeNumber;
this.item.diyCubeResult = _value.diyCubeResult;
this.styleDialogVisible = false;
}
},
handleNumberChange(e) {
this.item.diyCubeNumber = e;
this.initDefault()
},
// **************************************************************************** 自定义魔方相关
init() {
this.initDefault()
if (!this.item.diyCubeResult.length) {
const _traght = 'magic_1';
const _value = JSON.parse(JSON.stringify(magic_default[_traght]));
this.item.diyCubeNumber = _value.diyCubeNumber;
this.item.diyCubeResult = _value.diyCubeResult;
}
},
// 处理默认魔方数据
initDefault() {
// 此处布局为先行后列,所以i是纵轴y坐标,j是横轴x坐标
this.diyCubeData = [];
for (let i = 0; i < this.item.diyCubeNumber; i++) {
let _arr = []
for (let j = 0; j < this.item.diyCubeNumber; j++) {
let cube = { ...this.cube }
cube.x = j
cube.y = i
_arr.push(cube)
}
this.diyCubeData.push(_arr)
}
},
// 处理默认魔方块点击事件
handleDefaultMagic(item) {
if (!this.cubeEdit) {
// 将当前点击位置打标点
const key = this.mergeKey(item.y, item.x);
// 为了防止鼠标不移动,将当前块设为单独块
this.currentCubeKey.push(key);
// 记录开始位置
this.currentCubeStartKey = key;
// 当前魔方为编辑状态
this.cubeEdit = true;
} else {
// 将编辑临时数组进行排序,进行结束画框标记计算
let keys = this.currentCubeKey.sort((a, b) => a - b);
// 取出开始位置的坐标
const start = this.untieKey(keys[0]);
// 取出结束位置的坐标
const end = this.untieKey(keys[keys.length - 1]);
// 计算完成的当前选中魔方块
const temp = {
x: start.x,
y: start.y,
height: end.y - start.y + 1,
width: end.x - start.x + 1,
url: '',
link: '',
linkname: ''
}
// 合并数据
const result = [...this.item.diyCubeResult, temp];
this.item.diyCubeResult = result;
// console.log(this.item.diyCubeResult);
// 改变生成的魔方数据选中下标
this.currentCubeIndex = this.item.diyCubeResult.length - 1;
// 清除临时数据,方便下次进行计算
this.currentCubeKey = []
// 将魔方改为正常状态
this.cubeEdit = false;
}
},
// 魔方默认块的移入事件
mouseoverDefaultMagic(item2) {
// console.log(item2);
// 如果当前不是编辑状态,则直接返回
if (!this.cubeEdit) return
// 定义一个空数组,用于存储当前魔方块的key
const keys = [];
// 取出当前魔方块的首位数据
const start = this.untieKey(this.currentCubeStartKey)
// 取出当前魔方块的结尾数据
const end = { ...item2 }
// 处理魔方块的y和x,从小到大,方便后续计算、追加数据
const ys = [start.y, end.y].sort()
const xs = [start.x, end.x].sort()
// 判定是否重叠
if (this.antiCollision(start, end)) {
return;
}
for (let i = ys[0]; i <= ys[1]; i++) {
for (let j = xs[0]; j <= xs[1]; j++) {
keys.push(this.mergeKey(i, j))
}
}
this.currentCubeKey = keys
},
antiCollision(start, end) {
// 有可能从右边从左边选,导致 start.x > end.y,所以要排序
// 保证 rec1 [x1,y1,x2,y2] (x1,y1)为左上角坐标,(x2,y2)为右下角坐标
const xs = [start.x, end.x].sort();
const ys = [start.y, end.y].sort();
// 因为 end 记录的是 li 块的左上角坐标,构成矩形区域的话,应该算 li 块右下角坐标,所以 + 1
const rec1 = [xs[0], ys[0], xs[1] + 1, ys[1] + 1]
// console.log(rec1, 'rec1');
for (let i = 0; i < this.item.diyCubeResult.length; i++) {
const item = this.item.diyCubeResult[i];
const rec2 = [item.x, item.y, item.x + item.width, item.y + item.height]
// console.log(rec2, 'rec2');
const isIntersect = this.isIntersect(rec1, rec2);
if (isIntersect) return true
}
return false
},
// 切换生成的代码块选中状态
clickDiyMagic(index) {
if (this.currentCubeIndex == index) return
this.currentCubeIndex = index
},
// 移除选中的方框
removeDiyMagic(index) {
this.item.diyCubeResult.splice(index, 1)
if (this.item.diyCubeResult.length === 0) {
this.currentCubeIndex = -1
} else {
this.currentCubeIndex = this.item.diyCubeResult.length - 1
}
},
// 边界处理
handleMouseLeave() {
this.currentCubeKey = []
this.cubeEdit = false;
},
// ****************** 方法库
// 核心判定两个矩形是否重叠
isIntersect(rec1, rec2) {
/**
* 核心
* 思想:两矩形右边界的最小值大于两矩形左边界的最大值,说明两重叠,两矩形下边界的最小值大于两矩形上边界的最大值,说明两重叠
*/
return (Math.min(rec1[2], rec2[2]) > Math.max(rec1[0], rec2[0]) &&
Math.min(rec1[3], rec2[3]) > Math.max(rec1[1], rec2[1]));
},
// 获取当前块的唯一key值
mergeKey(y, x) {
return Number(y + (x * 10));
},
// 解析 key 值
untieKey(key) {
if (key >= 10) {
return { x: Math.floor((key % 100) / 10), y: key % 10 };
} else {
return { x: 0, y: key };
}
},
// 选择完成的魔方块的样式
getStyle(item) {
const { x, y, width, height } = item;
let style = {
left: `${x * this.itemWidth}px`,
top: `${y * this.itemWidth}px`,
width: `${width * this.itemWidth}px`,
height: `${height * this.itemWidth}px`
}
return style
}
}
}
</script>
<style lang="scss" scoped>
.dialog-box {
padding: 20px;
display: grid;
grid-template-columns: repeat(3, calc(33.33% - 20px));
grid-gap: 20px;
max-height: 500px;
overflow: auto;
.img-item-box {
text-align: center;
.img-item {
background-color: #f7f8fa;
padding: 10px;
box-sizing: border-box;
margin-bottom: 10px;
border: 1px solid #eee;
cursor: pointer;
width: 260px;
height: 200px;
&.active {
border-color: var(--primary);
}
}
}
}
.clearbox {
&::after {
content: '';
display: block;
clear: both;
}
}
.magic-cube {
.magic-box {
position: relative;
margin: 16px auto;
display: block !important;
.diy-magic-item {
position: absolute;
background-color: #e8f7fd;
border: 1px solid #bdf;
box-sizing: border-box;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
i {
position: absolute;
font-size: 20px;
right: -10px;
top: -10px;
color: #bbb;
display: none;
z-index: 999
}
img {
height: 100%;
width: 100%;
vertical-align: middle;
object-fit: cover;
}
&.active {
border-color: var(--primary);
i {
display: block;
}
}
}
.defaule-row {
display: flex;
&:first-child {
.defaule-col {
border-top: 1px solid #e5e5e5;
}
}
.defaule-col {
border-left: 1px solid #e5e5e5;
border-bottom: 1px solid #e5e5e5;
cursor: pointer;
background: #f8f8f8;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
&.item-seleting {
background-color: #e8f7fd;
i {
display: none;
}
}
i {
color: #bbb;
pointer-events: none;
}
&:last-child {
border-right: 1px solid #e5e5e5;
}
}
}
}
}
</style>
// 中间画板的展现,移动端代码相同,注意 rpx 和 px 的换算
<template>
<div class="middle-magic-cube component-top-position" :style="{
backgroundColor: item.comp_bg,
padding: `${item.padding_top}px 0 ${item.padding_bottom}px`
}">
<div class="cube-box" :style="{
margin: `0 ${item.padding_left_right}px`,
height: boxHeight
}">
<div class="diy-magic-item" v-for="(it,idx) in item.diyCubeResult" :key="idx" :style="getStyle(it)">
<div class="diy-magic-item-inner" :style="{
backgroundImage: `url(${it.url})`,
borderRadius: `${item.top_radius}px ${item.top_radius}px ${item.bottom_radius}px ${item.bottom_radius}px`,}">
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['item'],
computed: {
itemWidth() {
return (375 - this.item.padding_left_right * 2) / (this.item.diyCubeNumber || 2);
},
// 这里主要是处理,风格十一,我只使用了上半部分,下半部分不需要展示
boxHeight() {
if (this.item.comp_style === 11) {
// 取纵轴最大y
let y = 0;
this.item.diyCubeResult.forEach(element => y = Math.max(y, (element.y + element.height)));
return `${this.itemWidth * y}px`
} else {
return `${375 - (this.item.padding_left_right * 2 - 1)}px`
}
}
},
methods: {
handleActive() {
this.$eventBus.$emit("on_component_active", this.item);
},
// 选择完成的魔方块的样式
getStyle(item) {
const { x, y, width, height } = item;
let style = {
left: `${x * this.itemWidth}px`,
top: `${y * this.itemWidth}px`,
width: `${width * this.itemWidth}px`,
height: `${height * this.itemWidth}px`,
padding: `${this.item.image_space / 2}px`,
}
return style
}
}
}
</script>
<style lang="scss" scoped>
.middle-magic-cube {
height: 100%;
width: 100%;
box-sizing: border-box;
}
.cube-box {
position: relative;
height: 375px;
max-width: 375px;
overflow: hidden;
.diy-magic-item {
position: absolute;
box-sizing: border-box;
.diy-magic-item-inner {
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
}
}
}
</style>
// 固定风格 1-10 的基本数据
export default {
magic_1: {
diyCubeNumber: 2,
diyCubeResult: [{
x: 0,
y: 0,
height: 1,
width: 2,
url: '',
link: '',
linkname: ''
}, {
x: 0,
y: 1,
height: 1,
width: 2,
url: '',
link: '',
linkname: ''
}]
}, magic_2: {
diyCubeNumber: 2,
diyCubeResult: [{
x: 0,
y: 0,
height: 2,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 1,
y: 0,
height: 2,
width: 1,
url: '',
link: '',
linkname: ''
}]
}, magic_3: {
diyCubeNumber: 3,
diyCubeResult: [{
x: 0,
y: 0,
height: 3,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 1,
y: 0,
height: 3,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 2,
y: 0,
height: 3,
width: 1,
url: '',
link: '',
linkname: ''
}]
}, magic_4: {
diyCubeNumber: 2,
diyCubeResult: [{
x: 0,
y: 0,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 1,
y: 0,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 0,
y: 1,
height: 1,
width: 2,
url: '',
link: '',
linkname: ''
}]
}, magic_5: {
diyCubeNumber: 2,
diyCubeResult: [{
x: 0,
y: 0,
height: 1,
width: 2,
url: '',
link: '',
linkname: ''
}, {
x: 0,
y: 1,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 1,
y: 1,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}]
}, magic_6: {
diyCubeNumber: 2,
diyCubeResult: [{
x: 0,
y: 0,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 0,
y: 1,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 1,
y: 0,
height: 2,
width: 1,
url: '',
link: '',
linkname: ''
}]
}, magic_7: {
diyCubeNumber: 2,
diyCubeResult: [{
x: 0,
y: 0,
height: 2,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 0,
y: 1,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 1,
y: 1,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}]
}, magic_8: {
diyCubeNumber: 2,
diyCubeResult: [{
x: 0,
y: 0,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 0,
y: 1,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 1,
y: 0,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 1,
y: 1,
height: 1,
width: 1,
url: '',
link: '',
linkname: ''
}]
}, magic_9: {
diyCubeNumber: 6,
diyCubeResult: [{
x: 0,
y: 0,
height: 3,
width: 3,
url: '',
link: '',
linkname: ''
}, {
x: 3,
y: 0,
height: 3,
width: 3,
url: '',
link: '',
linkname: ''
}, {
x: 0,
y: 3,
height: 3,
width: 2,
url: '',
link: '',
linkname: ''
}, {
x: 2,
y: 3,
height: 3,
width: 2,
url: '',
link: '',
linkname: ''
}, {
x: 4,
y: 3,
height: 3,
width: 2,
url: '',
link: '',
linkname: ''
}]
}, magic_10: {
diyCubeNumber: 4,
diyCubeResult: [{
x: 0,
y: 0,
height: 4,
width: 2,
url: '',
link: '',
linkname: ''
}, {
x: 2,
y: 0,
height: 2,
width: 2,
url: '',
link: '',
linkname: ''
}, {
x: 2,
y: 2,
height: 2,
width: 1,
url: '',
link: '',
linkname: ''
}, {
x: 3,
y: 2,
height: 2,
width: 1,
url: '',
link: '',
linkname: ''
}]
}
}