parent
0b9ebaf5c1
commit
e2cd246b21
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="slider w">
|
||||
<el-slider v-model="internal_value" :min="min" :max="max" :step="step" />
|
||||
<input-number v-model="internal_value" class="slider-input" :min="min" :max="max"></input-number>
|
||||
<el-slider v-model="modelValue" :min="min" :max="max" :step="step" />
|
||||
<input-number v-model="modelValue" class="slider-input" :min="min" :max="max"></input-number>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ const props = defineProps({
|
|||
default: 1,
|
||||
},
|
||||
});
|
||||
const internal_value = defineModel({ type: Number, default: 0 });
|
||||
const modelValue = defineModel({ type: Number, default: 0 });
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.slider {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
<el-image :src="hot_list.img" class="w img" @selectstart.prevent @contextmenu.prevent @dragstart.prevent></el-image>
|
||||
</div>
|
||||
<div ref="areaRef" class="area" :style="init_drag_style"></div>
|
||||
<div v-for="(item, index) in hot_list.hot" :key="index" class="area-box" :style="rect_style(item.drag_start, item.drag_end)" @mousedown.prevent="start_drag_area_box(index, $event)" @dblclick="dbl_drag_event(item, index)">
|
||||
<div v-for="(item, index) in hot_list.data" :key="index" class="area-box" :style="rect_style(item.drag_start, item.drag_end)" @mousedown.prevent="start_drag_area_box(index, $event)" @dblclick="dbl_drag_event(item, index)">
|
||||
<div class="del-btn" @click.stop="del_area_event(index)"><icon name="close"></icon></div>
|
||||
<div class="drag-btn" :data-index="index" @mousedown.prevent="start_drag_btn(index, $event)"></div>
|
||||
<div class="text">
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
<div class="size-16 fw mb-10">图片热区</div>
|
||||
<div class="size-12 cr-9 mb-20">框选热区范围,双击设置热区信息</div>
|
||||
<div class="flex-col gap-20 item">
|
||||
<div v-for="(item, index) in hot_list.hot" :key="index" class="flex-row align-c gap-10">
|
||||
<div v-for="(item, index) in hot_list.data" :key="index" class="flex-row align-c gap-10">
|
||||
<el-input v-model="item.name" class="name" placeholder="名称"></el-input>
|
||||
<url-value v-model="item.link"></url-value>
|
||||
<icon name="del" size="20" @click="del_event(index)"></icon>
|
||||
|
|
@ -89,16 +89,9 @@ const hot_list = ref<hotData>({
|
|||
img: '',
|
||||
img_height: 1,
|
||||
img_width: 1,
|
||||
hot: [],
|
||||
data: [],
|
||||
});
|
||||
const hot_list_index = ref(0);
|
||||
watch(
|
||||
() => modelValue.value,
|
||||
(val) => {
|
||||
hot_list.value = cloneDeep(val);
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
|
||||
//#region 左侧画布-----------------------------------------------start
|
||||
const imgBoxRef = ref<HTMLElement | null>(null);
|
||||
|
|
@ -134,8 +127,8 @@ const end_drag = (event: MouseEvent) => {
|
|||
if (!imgBoxRef.value) return;
|
||||
init_drag_style.value = ``;
|
||||
if (rect_end.value.width > 16 && rect_end.value.height > 16) {
|
||||
hot_list.value.hot.push({
|
||||
name: '热区' + (hot_list.value.hot.length + 1),
|
||||
hot_list.value.data.push({
|
||||
name: '热区' + (hot_list.value.data.length + 1),
|
||||
link: {},
|
||||
drag_start: cloneDeep(rect_start.value),
|
||||
drag_end: cloneDeep(rect_end.value),
|
||||
|
|
@ -143,6 +136,7 @@ const end_drag = (event: MouseEvent) => {
|
|||
}
|
||||
rect_end.value = { x: 0, y: 0, width: 0, height: 0 };
|
||||
};
|
||||
|
||||
const area_box_point = ref({ x: 0, y: 0 });
|
||||
// area-box
|
||||
const dbl_drag_event = (item: hotListData, index: number) => {
|
||||
|
|
@ -155,15 +149,15 @@ const start_drag_area_box = (index: number, event: MouseEvent) => {
|
|||
hot_list_index.value = index;
|
||||
event.stopPropagation();
|
||||
drag_box_bool.value = true;
|
||||
let clone_drag_start = cloneDeep(hot_list.value.hot[hot_list_index.value].drag_start);
|
||||
let clone_drag_end = cloneDeep(hot_list.value.hot[hot_list_index.value].drag_end);
|
||||
let clone_drag_start = cloneDeep(hot_list.value.data[hot_list_index.value].drag_start);
|
||||
let clone_drag_end = cloneDeep(hot_list.value.data[hot_list_index.value].drag_end);
|
||||
// 记录原始位置
|
||||
area_box_point.value = {
|
||||
x: clone_drag_start.x - event.clientX,
|
||||
y: clone_drag_start.y - event.clientY,
|
||||
};
|
||||
|
||||
// 当子元素拖拽方法触发后夫元素方法不触发
|
||||
// 当子元素拖拽方法触发后父元素方法不触发
|
||||
document.onmousemove = (areaBoxEvent) => {
|
||||
areaBoxEvent.stopPropagation();
|
||||
if (drag_box_bool.value) {
|
||||
|
|
@ -186,8 +180,8 @@ const start_drag_area_box = (index: number, event: MouseEvent) => {
|
|||
if (new_coordinate.y + Math.max(clone_drag_end.height, 1) > imgBoxRef.value.getBoundingClientRect().height) {
|
||||
new_coordinate.y = imgBoxRef.value.getBoundingClientRect().height - Math.max(clone_drag_end.height, 1) - 7;
|
||||
}
|
||||
hot_list.value.hot[hot_list_index.value].drag_start.x = new_coordinate.x;
|
||||
hot_list.value.hot[hot_list_index.value].drag_start.y = new_coordinate.y;
|
||||
hot_list.value.data[hot_list_index.value].drag_start.x = new_coordinate.x;
|
||||
hot_list.value.data[hot_list_index.value].drag_start.y = new_coordinate.y;
|
||||
}
|
||||
};
|
||||
document.onmouseup = (areaBoxEvent) => {
|
||||
|
|
@ -200,8 +194,8 @@ const start_drag_btn = (index: number, event: MouseEvent) => {
|
|||
hot_list_index.value = index;
|
||||
event.stopPropagation();
|
||||
drag_box_scale_bool.value = true;
|
||||
let clone_drag_start = hot_list.value.hot[hot_list_index.value].drag_start;
|
||||
let clone_drag_end = hot_list.value.hot[hot_list_index.value].drag_end;
|
||||
let clone_drag_start = hot_list.value.data[hot_list_index.value].drag_start;
|
||||
let clone_drag_end = hot_list.value.data[hot_list_index.value].drag_end;
|
||||
document.onmousemove = (dragBtnEvent) => {
|
||||
dragBtnEvent.stopPropagation();
|
||||
//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
|
||||
|
|
@ -209,7 +203,7 @@ const start_drag_btn = (index: number, event: MouseEvent) => {
|
|||
if (!imgBoxRef.value) return;
|
||||
clone_drag_end.x = dragBtnEvent.clientX - imgBoxRef.value.getBoundingClientRect().left;
|
||||
clone_drag_end.y = dragBtnEvent.clientY - imgBoxRef.value.getBoundingClientRect().top;
|
||||
hot_list.value.hot[hot_list_index.value].drag_end = {
|
||||
hot_list.value.data[hot_list_index.value].drag_end = {
|
||||
x: clone_drag_end.x,
|
||||
y: clone_drag_end.y,
|
||||
width: clone_drag_end.x - clone_drag_start.x > 0 ? clone_drag_end.x - clone_drag_start.x : 0,
|
||||
|
|
@ -223,7 +217,7 @@ const start_drag_btn = (index: number, event: MouseEvent) => {
|
|||
};
|
||||
};
|
||||
const del_area_event = (index: number) => {
|
||||
hot_list.value.hot.splice(index, 1);
|
||||
hot_list.value.data.splice(index, 1);
|
||||
};
|
||||
const rect_style = computed(() => {
|
||||
return (start: rectCoords, end: rectCoords) => {
|
||||
|
|
@ -234,7 +228,7 @@ const rect_style = computed(() => {
|
|||
|
||||
//#region 右侧热区编辑-----------------------------------------------start
|
||||
const del_event = (index: number) => {
|
||||
hot_list.value.hot.splice(index, 1);
|
||||
hot_list.value.data.splice(index, 1);
|
||||
};
|
||||
//#endregion 右侧热区编辑-----------------------------------------------end
|
||||
|
||||
|
|
@ -248,8 +242,8 @@ const hot_close_event = () => {
|
|||
hot_dialog_visible.value = false;
|
||||
};
|
||||
const hot_confirm_event = () => {
|
||||
hot_list.value.hot[hot_list_index.value].link = form.value.link;
|
||||
hot_list.value.hot[hot_list_index.value].name = form.value.name;
|
||||
hot_list.value.data[hot_list_index.value].link = form.value.link;
|
||||
hot_list.value.data[hot_list_index.value].name = form.value.name;
|
||||
hot_close_event();
|
||||
};
|
||||
//#endregion 设置热区弹窗-----------------------------------------------end
|
||||
|
|
@ -260,6 +254,7 @@ const open_hot_event = () => {
|
|||
if (modelValue.value.img.length > 0) {
|
||||
dialog_visible.value = true;
|
||||
hot_list.value = cloneDeep(modelValue.value);
|
||||
console.log(1);
|
||||
} else {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
|
|
@ -274,16 +269,16 @@ const close_event = () => {
|
|||
};
|
||||
// 确认回调
|
||||
const confirm_event = () => {
|
||||
if (hot_list.value.hot.length > 0) {
|
||||
if (hot_list.value.data.length > 0) {
|
||||
// 筛选数组hot中所有的link是否有空值,如果有则提示出来
|
||||
if (is_obj_empty(hot_list.value.hot)) {
|
||||
if (is_obj_empty(hot_list.value.data)) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: '请先设置热区',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const no_link_list = hot_list.value.hot.filter((item) => {
|
||||
const no_link_list = hot_list.value.data.filter((item) => {
|
||||
return is_obj_empty(item.link);
|
||||
});
|
||||
if (no_link_list.length > 0) {
|
||||
|
|
@ -292,7 +287,7 @@ const confirm_event = () => {
|
|||
} else {
|
||||
hot_list.value.img_height = imgRef.value?.clientHeight || 0;
|
||||
hot_list.value.img_width = imgRef.value?.clientWidth || 0;
|
||||
modelValue.value = hot_list.value;
|
||||
modelValue.value = cloneDeep(hot_list.value);
|
||||
close_event();
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div ref="containerRef" class="oh" :style="style_container">
|
||||
<div ref="hotRef" class="hot re" :style="style">
|
||||
<image-empty v-model="img" class="w" error-img-style="width:10rem;height:10rem;" error-style="padding:15rem 0;"></image-empty>
|
||||
<div v-for="(item, index) in hot" :key="index" class="hot_box" :style="rect_style(item.drag_start, item.drag_end)"></div>
|
||||
<div v-for="(item, index) in hot_data" :key="index" class="hot_box" :style="rect_style(item.drag_start, item.drag_end)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -19,41 +19,44 @@ const hotRef = ref<HTMLElement | null>(null);
|
|||
const style = ref('');
|
||||
const style_container = ref('');
|
||||
const img = ref('');
|
||||
const hot = ref<hotListData[]>([]);
|
||||
const hot_data = ref<hotListData[]>([]);
|
||||
// 热区组件图片的宽高
|
||||
const img_width = ref(1);
|
||||
const img_height = ref(1);
|
||||
// containerRef的宽高
|
||||
const w_scale1 = ref(1);
|
||||
const h_scale1 = ref(1);
|
||||
// hotRef的宽高
|
||||
const w_scale2 = ref(1);
|
||||
const h_scale2 = ref(1);
|
||||
watch(
|
||||
props.value,
|
||||
(newVal, oldValue) => {
|
||||
const new_content = newVal?.content || {};
|
||||
const new_style = newVal?.style || {};
|
||||
img.value = new_content?.img[0];
|
||||
hot.value = new_content?.hot.hot;
|
||||
hot_data.value = new_content?.hot?.data || [];
|
||||
img_width.value = new_content?.hot.img_width || 1;
|
||||
img_height.value = new_content?.hot.img_height || 1;
|
||||
style_container.value = common_styles_computer(new_style.common_style);
|
||||
nextTick(() => {
|
||||
if (containerRef.value && hotRef.value) {
|
||||
// 原图片的宽和高和实际展示的图片宽和高的比例
|
||||
w_scale1.value = containerRef.value?.clientWidth / img_width.value;
|
||||
h_scale1.value = containerRef.value?.clientHeight / img_height.value;
|
||||
|
||||
// 坐标缩小比例 containerRef的宽高除以hotRef的宽高
|
||||
w_scale2.value = hotRef.value?.clientWidth / containerRef.value?.clientWidth;
|
||||
h_scale2.value = hotRef.value?.clientHeight / containerRef.value?.clientHeight;
|
||||
}
|
||||
});
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
|
||||
const rect_style = computed(() => {
|
||||
return (start: rectCoords, end: rectCoords) => {
|
||||
let w_scale1 = 1;
|
||||
let h_scale1 = 1;
|
||||
let w_scale2 = 1;
|
||||
let h_scale2 = 1;
|
||||
if (containerRef.value && hotRef.value) {
|
||||
// 原图片的宽和高和实际展示的图片宽和高的比例
|
||||
w_scale1 = containerRef.value?.clientWidth / img_width.value;
|
||||
h_scale1 = containerRef.value?.clientHeight / img_height.value;
|
||||
|
||||
// 坐标缩小比例 containerRef的宽高除以hotRef的宽高
|
||||
w_scale2 = hotRef.value?.clientWidth / containerRef.value?.clientWidth;
|
||||
h_scale2 = hotRef.value?.clientHeight / containerRef.value?.clientHeight;
|
||||
}
|
||||
console.log('containerRef', containerRef.value?.clientWidth, containerRef.value?.clientHeight, 'hotRef', hotRef.value?.clientWidth, hotRef.value?.clientHeight);
|
||||
console.log('w_scale1', w_scale1, 'h_scale1', h_scale1, 'w_scale2', w_scale2, 'h_scale2', h_scale2);
|
||||
return `left: ${start.x * w_scale1 * w_scale2}px;top: ${start.y * h_scale1 * h_scale2}px;width: ${Math.max(end.width * w_scale1 * w_scale2, 1)}px;height: ${Math.max(end.height * h_scale1 * h_scale2, 1)}px;display: flex;`;
|
||||
return `left: ${start.x * w_scale1.value * w_scale2.value}px;top: ${start.y * h_scale1.value * h_scale2.value}px;width: ${Math.max(end.width * w_scale1.value * w_scale2.value, 1)}px;height: ${Math.max(end.height * h_scale1.value * h_scale2.value, 1)}px;display: flex;`;
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
|
@ -61,8 +64,10 @@ const rect_style = computed(() => {
|
|||
.hot {
|
||||
min-height: 1rem;
|
||||
.hot_box {
|
||||
background-color: red;
|
||||
background: rgba(42, 148, 255, 0.25);
|
||||
border: 1px dashed #8ec6ff;
|
||||
position: absolute;
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<card-container class="common-content-height">
|
||||
<div class="mb-12">内容设置</div>
|
||||
<el-form-item label="上传照片">
|
||||
<upload v-model="form.img" :limit="1" is-tips tips-text="请先选择照片,图片宽度750px,高度不限" @update:model-value="update_hot_data"></upload>
|
||||
<upload v-model="form.img" :limit="1" is-tips tips-text="请先选择照片,图片宽度750px,高度不限" @update:model-value="update_upload_data"></upload>
|
||||
</el-form-item>
|
||||
<hot v-model="form.hot"></hot>
|
||||
</card-container>
|
||||
|
|
@ -23,13 +23,13 @@ const props = defineProps({
|
|||
});
|
||||
const form = ref(props.value);
|
||||
|
||||
const update_hot_data = (val: any) => {
|
||||
const update_upload_data = (val: any) => {
|
||||
if (val.length > 0) {
|
||||
form.value.hot.img = val[0].url;
|
||||
} else {
|
||||
form.value.hot.img = '';
|
||||
}
|
||||
form.value.hot.hot = [];
|
||||
form.value.hot.data = [];
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -15,8 +15,10 @@ const defaultHotZone: DefaultHotZone = {
|
|||
img: [],
|
||||
hot: {
|
||||
// /src/assets/images/components/model-user-info/avatar.png
|
||||
img_height: 1,
|
||||
img_width: 1,
|
||||
img: '',
|
||||
hot: [],
|
||||
data: [],
|
||||
},
|
||||
},
|
||||
style: {
|
||||
|
|
|
|||
|
|
@ -186,7 +186,6 @@ watch(
|
|||
// 父组件调用的方法
|
||||
const emits = defineEmits(['rightUpdate']);
|
||||
const activeNames = reactive(['1', '2']);
|
||||
console.log(import.meta.url);
|
||||
const components = reactive([
|
||||
{
|
||||
title: '基础组件',
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ declare global {
|
|||
img: string;
|
||||
img_width: number;
|
||||
img_height: number;
|
||||
hot: hotListData[];
|
||||
data: hotListData[];
|
||||
};
|
||||
type rectCoords = {
|
||||
x: number;
|
||||
|
|
|
|||
Loading…
Reference in New Issue