vue项目three.js&&vue-draggable-resizable组件实现图片添加热点
Vue.Draggable
SortableJS/Vue.Draggable: Vue.Draggable 是 Sortable.js 的 Vue.js 封装组件,提供了拖放排序功能,可以在 Vue 应用中轻松实现列表元素的可拖拽重排。
项目地址:https://gitcode.com/gh_mirrors/vu/Vue.Draggable
免费下载资源
·
通过使用three.js&&vue-draggable-resizable组件实现图片添加热点,场景世界坐标和平面热点二维坐标互转
项目描述:当前项目需求是,场景图中可以手动添加热点,并且热点可以在场景图上拖拽改变位置。
实现逻辑:
npm install --save vue-draggable-resizable
main.js添加如下代码
import VueDraggableResizable from 'vue-draggable-resizable'
import 'vue-draggable-resizable/dist/VueDraggableResizable.css'
Vue.component('vue-draggable-resizable', VueDraggableResizable)
首先通过three.js渲染场景,几何体采用球几何体,纹理采用整张图片贴图,然后dom中引用vue-draggable-resizable组件渲染热点,场景的position:relative;热点position:absolute;代码如下:
<div id="divContainer">
<!--场景展示容器start-->
<div ref="container" class="vrImage" ></div>
<vue-draggable-resizable
v-for="(item, index) in hotspot"
v-if="item.imageUrl"
:key="index"
:id="index"
:x.sync="item.left"
:y.sync="item.top"
:min-width="50"
:min-height="50"
:parent="false"
:grid="[1,1]"
:active="index === dragActiveIndex"
:prevent-deactivation="index === dragActiveIndex"
class-name="dragging"
class-name-active= "activeClass"
class-name-handle= "activeHandle"
@dragging="onDrag"
@dragstop = "onDragStop"
@activated="onActivated(index)"
>
<div class="iconDiv">
<span>{{item.name}}</span>
<el-image
:src="item.imageUrl"></el-image>
</div>
</vue-draggable-resizable>
<!--场景展示容器end-->
</div>
<style lang="less">
#divContainer {
position: relative;
overflow: hidden;
.vrImage {
height: 593px;
border: 1px solid;
}
.dragging {
position: absolute;
top:0;
height: 80px !important;
width: 80px !important;
transform: translateX(-50%) translateY(-50%);
}
.activeClass{
border: 2px solid yellow;
height: 80px !important;
width: 80px !important;
border-radius: 15px;
}
.activeHandle {
border: 0;
}
}
}
</style>
如果使用过vue-draggable-resizable这个插件应该知道,改组件的x、y值是相对与父级div的,那父级div的原点是左上角的顶点,二维坐标为(0, 0);当相机旋转,场景世界坐标和平面二维坐标互转,这里参考这个demo:
http://www.wjceo.com/blog/threejs2/2018-06-25/175.html
平面热点转二维坐标,代码如下:
setSceneGet3DPos (x, y) {
// 根据鼠标位置创建射线
let containerWidth = this.$refs.container.offsetWidth;
let containerHeight = this.$refs.container.offsetHeight;
let mouse = new THREE.Vector3();
x = (x / containerWidth) * 2 - 1;
y = -(y / containerHeight) * 2 + 1;
let newRay = new THREE.Raycaster();
newRay.setFromCamera({x: x, y: y}, this.camera);
// 通过射线与小球的交点获取新热点的位置
let newHotPos = newRay.intersectObject(this.mesh)[0].point; // mesh为场景网格,采用球几何体
newHotPos.setLength(this.radius - 10);
mouse.x = newHotPos.x.toFixed(4);
mouse.y = newHotPos.y.toFixed(4);
mouse.z = newHotPos.z.toFixed(4);
return mouse;
},
onDrag(x, y) {
this.controls.enabled = false;
let mouse = this.setSceneGet3DPos(x + 40, y + 40); // 40 为图片大小的一半,本场景图片大小为80x80
this.group.children[this.dragActiveIndex].position.set(mouse.x, mouse.y, mouse.z);
},
onActivated(index) {
this.dragActiveIndex = index;
this.hotSpotIndex = this.dragActiveIndex; // 热点下标
},
onDragStop(x, y) {
this.controls.enabled = true;
let mouse = this.setSceneGet3DPos(x + 40, y + 40); // 40 为图片大小的一半,本场景图片大小为80x80
this.scenesObj.scenes[this.sceneIndex].hotspot[this.dragActiveIndex].atv = mouse.x;
this.scenesObj.scenes[this.sceneIndex].hotspot[this.dragActiveIndex].ath = mouse.y;
this.scenesObj.scenes[this.sceneIndex].hotspot[this.dragActiveIndex].atz = mouse.z;
}
球面坐标转平面坐标:
this.render(
this.hotSpotChange();
)
hotSpotChange() {
// 获取到窗口的一半高度和一半宽度
let container = this.$refs.container;
if (this.group.children.length === 0) return;
let halfWidth = container.offsetWidth / 2;
let halfHeight = container.offsetHeight / 2;
let scene = this.scenesObj.scenes[this.sceneIndex];
this.group.children.forEach((item, index) => {
let vector = item.position.clone().project(this.camera);
let hotspot = scene.hotspot[index];
hotspot.left = vector.x * halfWidth + halfWidth - 40; // 40 为图片大小的一半,本场景图片大小为80x80
hotspot.top = -vector.y * halfHeight + halfHeight - 40;
if (document.getElementById(index.toString()) !== null) {
if (vector.z > 1) {
document.getElementById(index.toString()).style.visibility = "hidden";
} else {
document.getElementById(index.toString()).style.visibility = "";
}
}
});
this.scenesObj.scenes.splice(this.sceneIndex, 1, scene); // 保持数据关联性
}
GitHub 加速计划 / vu / Vue.Draggable
4
1
下载
SortableJS/Vue.Draggable: Vue.Draggable 是 Sortable.js 的 Vue.js 封装组件,提供了拖放排序功能,可以在 Vue 应用中轻松实现列表元素的可拖拽重排。
最近提交(Master分支:4 个月前 )
431db153 - 2 年前
017ab498 - 3 年前
更多推荐
已为社区贡献3条内容
所有评论(0)