Commit 01b5923a by xhw

更新

parent 635433a1
<!DOCTYPE html>
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.d1{
width: 300px;
height: 300px;
background-color: rgb(231, 24, 24);
}
.p1:hover ~ .d1{
background-color: rgb(16, 243, 148);
}
</style>
<meta charset="UTF-8" />
<title>右键菜单-子菜单示例</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
body{margin:0;font-family:"Segoe UI",sans-serif;background:#f4f6f9;}
#board{width:100vw;height:100vh;background:#fff;position:relative;}
/* ===== 一级菜单 ===== */
#customContextMenu{
position:fixed;
border:1px solid #e0e0e0;
border-radius:6px;
background:#fff;
box-shadow:0 2px 8px rgba(0,0,0,.15);
padding:6px 0;
font-size:14px;
z-index:9999;
user-select:none;
display:none; /* 默认隐藏 */
}
#customContextMenu .menu-item{
padding:7px 26px 7px 12px;
cursor:pointer;
position:relative;
display:flex;
align-items:center;
gap:6px;
}
#customContextMenu .menu-item:hover{background:#f3f3f3;}
/* 有子菜单的箭头 */
#customContextMenu .hasChildren::after{
content:'';
position:absolute;
right:8px;
top:50%;
transform:translateY(-50%);
border:4px solid transparent;
border-left-color:#666;
}
/* ===== 二级菜单(子菜单) ===== */
.submenu{
position:absolute;
left:100%;
top:-6px; /* 与父项对齐微调 */
border:1px solid #e0e0e0;
border-radius:6px;
background:#fff;
box-shadow:0 2px 8px rgba(0,0,0,.15);
padding:6px 0;
display:none; /* 默认隐藏 */
min-width:120px;
}
</style>
</head>
<body>
<div class="d1">
<div class="p1"> hello </div>
<!-- 画布区域 -->
<div id="board">在此区域点击右键</div>
<!-- 自定义右键菜单 -->
<div id="customContextMenu">
<div class="menu-item" data-action="startCard">
<i class="fas fa-plus-circle"></i> 起始卡片
</div>
<div class="menu-item hasChildren" data-action="eventCard">
<i class="fas fa-plus-circle"></i> 事件卡片
<!-- 子菜单 -->
<div class="submenu">
<div class="menu-item" data-action="eventCard-attack"><i class="fas fa-sword"></i> 攻击事件</div>
<div class="menu-item" data-action="eventCard-defend"><i class="fas fa-shield-alt"></i> 防御事件</div>
<div class="menu-item" data-action="eventCard-story"><i class="fas fa-book-open"></i> 剧情事件</div>
</div>
</div>
<div class="menu-item" data-action="endCard">
<i class="fas fa-plus-circle"></i> 结局卡片
</div>
</div>
<script>
const board = document.getElementById('board');
const menuBox = document.getElementById('customContextMenu');
/* ===== 右键显示/隐藏 ===== */
board.addEventListener('contextmenu', e=>{
e.preventDefault();
showMenu(e.clientX, e.clientY);
});
document.addEventListener('click', hideMenu);
/* ===== 显示菜单 ===== */
function showMenu(x,y){
// 简单边界检测
const {innerWidth,innerHeight}=window;
const {offsetWidth,offsetHeight}=menuBox;
if(x+offsetWidth>innerWidth) x-=offsetWidth;
if(y+offsetHeight>innerHeight) y-=offsetHeight;
menuBox.style.left = x + 'px';
menuBox.style.top = y + 'px';
menuBox.style.display = 'block';
}
function hideMenu(){
menuBox.style.display = 'none';
// 同时隐藏所有子菜单
menuBox.querySelectorAll('.submenu').forEach(sm=>sm.style.display='none');
}
/* ===== 子菜单展开/收起 ===== */
menuBox.querySelectorAll('.hasChildren').forEach(item=>{
let timer=null;
const submenu=item.querySelector('.submenu');
item.addEventListener('mouseenter',()=>{
clearTimeout(timer);
submenu.style.display='block';
});
item.addEventListener('mouseleave',()=>{
timer=setTimeout(()=>submenu.style.display='none',150);
});
submenu.addEventListener('mouseenter',()=>clearTimeout(timer));
submenu.addEventListener('mouseleave',()=>submenu.style.display='none');
});
/* ===== 任意菜单/子菜单点击 ===== */
menuBox.addEventListener('click', e=>{
const action = e.target.closest('[data-action]')?.dataset.action;
if(action){
console.log('执行动作 =>', action); // 这里换成你自己的业务逻辑
hideMenu();
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
</html>
\ No newline at end of file
......@@ -184,7 +184,39 @@ cursor: pointer;
width: calc(100vw - 51px);
}
}
.label_left{
position: absolute;
top: -4px;
left: -60px;
width: 70px;
z-index: -10;
}
.label_left:hover{
/* opacity: 1;
top: -4px;
left: -60px;
width: 70px;
z-index: -10; */
/* transition: .3s;
opacity: 1; */
}
.label_right{
display: block;
text-align: left;
position: absolute;
top: -4px;
right: -74px;
width: 70px;
z-index: -10;
/* opacity: 0; */
}
/* .label_right:hover{
position: absolute;
top: -4px;
right: -74px;
width: 70px;
opacity: 1;
} */
/* Editing Drawflow */
......
......@@ -10,6 +10,28 @@ html, body {
border: 0;
}
.svgIcon_left{
position: absolute;
top: -13px;
left: -13px;
}
.svgIcon_left:hover{
cursor: pointer;
transform: scale(1.1);
transition: all 0.2s ease;
}
.svgIcon_right{
position: absolute;
top: -13px;
right: -13px;
}
.svgIcon_right:hover{
cursor: pointer;
transform: scale(1.1);
transition: all 0.2s ease;
}
#customContextMenu {
display: none;
position: absolute;
......
......@@ -165,7 +165,7 @@
</div>
<!-- 自定义右键菜单 -->
<div id="customContextMenu">
<!-- <div id="customContextMenu">
<div class="menu-item" data-action="startCard" >
<i class="fas fa-plus-circle"></i> 起始卡片
</div>
......@@ -177,7 +177,7 @@
</div>
<!-- <div class="menu-item" data-action="new">
<div class="menu-item" data-action="new">
<i class="fas fa-plus-circle"></i> 新建文件
</div>
<div class="menu-item" data-action="open">
......@@ -199,9 +199,47 @@
</div>
<div class="menu-item" data-action="info">
<i class="fas fa-info-circle"></i> 关于
</div> -->
</div>
</div> -->
<!-- 自定义右键菜单 -->
<div id="customContextMenu">
<div class="menu-item" data-action="startCard">
<i class="fas fa-plus-circle"></i> 起始卡片
</div>
<div class="menu-item hasChildren" data-action="eventCard">
<i class="fas fa-plus-circle"></i> 事件卡片
<!-- 子菜单 -->
<div class="submenu">
<div class="menu-item hasChildren" data-action="eventCard-attack">
<i class="fas fa-plus-circle"></i> 攻击事件
<div class="submenu">
<div class="menu-item" data-action="eventCard-defend"><i class="fas fa-shield-alt"></i></div>
<div class="menu-item" data-action="eventCard-defend"><i class="fas fa-shield-alt"></i></div>
</div>
</div>
<div class="menu-item" data-action="eventCard-defend"><i class="fas fa-shield-alt"></i> 防御事件</div>
<div class="menu-item" data-action="eventCard-story"><i class="fas fa-book-open"></i> 剧情事件</div>
</div>
</div>
<div class="menu-item hasChildren" data-action="conditionCard">
<i class="fas fa-plus-circle"></i> 条件卡片
<div class="submenu">
<div class="menu-item" data-action="conditionCard-huo"> <i class="fas fa-plus-circle"></i> 或事件 </div>
<div class="menu-item" data-action="conditionCard-yu"><i class="fas fa-shield-alt"></i> 与事件</div>
<div class="menu-item" data-action="conditionCard-fei"><i class="fas fa-book-open"></i> 非事件</div>
</div>
</div>
<div class="menu-item" data-action="endCard">
<i class="fas fa-plus-circle"></i> 结局卡片
</div>
</div>
<script>
class MyNodes {
constructor(input, output) {
......@@ -241,9 +279,52 @@
window.onload = function() {
rightMenu()
/* ===== 显示菜单 ===== */
function showMenu(x,y){
// 简单边界检测
const {innerWidth,innerHeight}=window;
const {offsetWidth,offsetHeight}=menuBox;
if(x+offsetWidth>innerWidth) x-=offsetWidth;
if(y+offsetHeight>innerHeight) y-=offsetHeight;
menuBox.style.left = x + 'px';
menuBox.style.top = y + 'px';
menuBox.style.display = 'block';
}
function hideMenu(){
menuBox.style.display = 'none';
// 同时隐藏所有子菜单
menuBox.querySelectorAll('.submenu').forEach(sm=>sm.style.display='none');
}
hideMenu()
menuBox.querySelectorAll('.hasChildren').forEach(item=>{
let timer=null;
const submenu=item.querySelector('.submenu');
item.addEventListener('mouseenter',()=>{
clearTimeout(timer);
submenu.style.display='block';
});
item.addEventListener('mouseleave',()=>{
timer=setTimeout(()=>submenu.style.display='none',150);
});
submenu.addEventListener('mouseenter',()=>clearTimeout(timer));
submenu.addEventListener('mouseleave',()=>submenu.style.display='none');
});
/* ===== 任意菜单/子菜单点击 ===== */
menuBox.addEventListener('click', e=>{
const action = e.target.closest('[data-action]')?.dataset.action;
if(action){
console.log('执行动作 =>', action); // 这里换成你自己的业务逻辑
hideMenu();
}
});
}
const menuBox = document.getElementById('customContextMenu');
var id = document.getElementById("drawflow");
const editor = new Drawflow(id);
editor.reroute = true;
......@@ -290,18 +371,31 @@
const output_class = connection.output_class
const input_index = parseInt(input_class.split("_")[1])
const output_index = parseInt(output_class.split("_")[1])
const name = editor.getNodeFromId(output_id).name
console.log(name)
// console.log(editor.getNodeFromId(input_id))
console.log(editor.getNodeFromId(input_id))
// console.log(editor.getNodeFromId(output_id))
// console.log(input_index,output_index)
//对比输入输出的数据类型
//得到对应的数据类型
const dataType_output = editor.getNodeFromId(output_id).data.node.output[output_index - 1]
const dataType_input = editor.getNodeFromId(input_id).data.node.input[input_index - 1]
console.log(dataType_output,dataType_input)
//得到当前端点的链接数组数据
const currentOutput = editor.getNodeFromId(input_id).inputs[input_class].connections
console.log(currentOutput)
// console.log(dataType_output,dataType_input)
if(dataType_output != dataType_input){
editor.removeSingleConnection(output_id, input_id, output_class, input_class)
}
// console.log(editor.getNodeFromId(output_id))
// console.log(editor.getNodeFromId(input_id))
// 对于条件卡片,只允许一个输入端点连接
if(currentOutput.length>1){
editor.removeSingleConnection(output_id, input_id, output_class, input_class)
}
})
......@@ -333,6 +427,7 @@
editor.on('removeReroute', function(id) {
// console.log("Reroute removed " + id);
})
/* DRAG EVENT */
......@@ -343,7 +438,7 @@
function positonXY(event) {
x = event.pageX; // 水平坐标(含滚动距离)
y = event.pageY; // 垂直坐标(含滚动距离)
console.log(`文档坐标:(${x}, ${y})`);
// console.log(`文档坐标:(${x}, ${y})`);
}
const controller = new AbortController();
......@@ -410,8 +505,19 @@
}
}
function onClickSvgIcon_left(args){
// console.log(args.parentElement.parentElement.id.slice(5))
const id = args.parentElement.parentElement.id.slice(5)
editor.addNodeInput(id)
}
function onClickSvgIcon_right(args){
const id = args.parentElement.parentElement.id.slice(5)
editor.addNodeOutput(id)
}
function drop(ev) {
console.log(ev)
console.log(ev.target)
if (ev.type === "touchend") {
var parentdrawflow = document.elementFromPoint( mobile_last_move.touches[0].clientX, mobile_last_move.touches[0].clientY).closest("#drawflow");
if(parentdrawflow != null) {
......@@ -573,7 +679,7 @@
}
}
function addNodeToDrawFlow_A(name, pos_x, pos_y){
function addNodeToDrawFlow_A(name, pos_x, pos_y,conditionType){
console.log(name, pos_x, pos_y)
if(editor.editor_mode === 'fixed') {
return false;
......@@ -666,7 +772,6 @@
`;
editor.addNode('email', 1, 0, pos_x, pos_y, 'email', {}, email );
break;
case 'template':
var template = `
<div>
......@@ -699,27 +804,92 @@
editor.addNode('personalized', 1, 1, pos_x, pos_y, 'personalized', {}, personalized );
break;
case 'dbclick':
var timer = 'svg' + new Date().getTime()
var dbclick = `
<div>
<div class="title-box"><i class="fas fa-mouse"></i> Db Click</div>
<div class="box dbclickbox" ondblclick="showpopup(event)">
Db Click here
<div class="modal" style="display:none">
<div class="modal-content">
<span class="close" onclick="closemodal(event)">&times;</span>
Change your variable {name} !
<input type="text" df-name>
</div>
</div>
<div id=${timer}>
<div class="title-box" style="">${conditionType=="conditionCard-fei"?"非":conditionType=="conditionCard-huo"?"或":"与"}</div>
<div class="box dbclickbox">
${conditionType=='conditionCard-fei'?'':' <svg t="1754546984413" onClick="onClickSvgIcon_left( ' + timer + ' )" id="" class="icon svgIcon_left" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7170" width="24" height="24"><path d="M512 942C274.9 942 82 749.11 82 512 82 274.9 274.9 82 512 82c237.11 0 430 192.9 430 430 0 237.11-192.89 430-430 430z m0-800c-204.02 0-370 165.98-370 370s165.98 370 370 370 370-165.98 370-370-165.98-370-370-370z" p-id="7171" fill="#8a8a8a"></path><path d="M512 768.27c-16.57 0-30-13.44-30-30V285.73c0-16.57 13.43-30 30-30s30 13.43 30 30v452.54c0 16.56-13.43 30-30 30z" p-id="7172" fill="#8a8a8a"></path><path d="M738.27 542H285.73c-16.57 0-30-13.43-30-30s13.43-30 30-30h452.54c16.56 0 30 13.43 30 30s-13.44 30-30 30z" p-id="7173" fill="#8a8a8a"></path></svg> '}
<div class="attrs" attr_left="bool bool bool" attr_right="no yes"></div>
</div>
</div>
`;
editor.addNode('dbclick', 1, 1, pos_x, pos_y, 'dbclick', { name: ''}, dbclick );
editor.addNode('dbclick', conditionType=="conditionCard-fei"?1:3, 2, pos_x, pos_y, 'dbclick', {"node":new MyNodes(['bool','bool','bool'],['bool','bool'])}, dbclick );
break;
default:
}
// console.log(document.getElementsByClassName("input"))
// console.log(document.getElementsByClassName("output"))
const input = document.getElementsByClassName("input")
const output = document.getElementsByClassName("output")
for(let i = 0; i < input.length; i++ ){
input[i].addEventListener('contextmenu', function(e){
e.preventDefault();
e.stopPropagation()
console.log(e.target.classList[1])
// console.log(e.target.parentElement.parentElement.id.slice(5))
const data = e.target.parentElement.parentElement.id.slice(5)
const inputOroutput = e.target.classList[0]
const currentPoint = parseInt(e.target.classList[1].split('_')[1])
// console.log(currentPoint)
// console.log(e.target.classList[0],e.target.classList[1])
// console.log(editor.getNodeFromId(data))
if(inputOroutput == "input"){
//拿到另一端的class id 进行删除 arr长度代表要删除的线段个数
const arr = editor.getNodeFromId(data).inputs[e.target.classList[1]].connections
// console.log(arr)
for(let j = 0; j < arr.length; j++ ){
// console.log(data,arr[j].node,e.target.classList[1],arr[j].input)
editor.removeSingleConnection(arr[j].node, data, arr[j].input, e.target.classList[1])
e.target.remove();
}
}
});
}
// for(let i = 0; i < output.length; i++ ){
// output[i].addEventListener('contextmenu', function(e){
// e.preventDefault();
// e.stopPropagation()
// console.log(e.target.classList[1])
// const data = e.target.parentElement.parentElement.id.slice(5)
// const outputOroutput = e.target.classList[0]
// const currentPoint = parseInt(e.target.classList[1].split('_')[1])
// console.log(currentPoint)
// console.log(e.target.classList[0],e.target.classList[1])
// console.log(editor.getNodeFromId(data))
// if(outputOroutput == "output"){
// //拿到另一端的class id 进行删除 arr长度代表要删除的线段个数
// const arr = editor.getNodeFromId(data).outputs[e.target.classList[1]].connections
// console.log(arr)
// for(let j = 0; j < arr.length; j++ ){
// console.log(arr[j].node, data, arr[j].output, e.target.classList[1])
// editor.removeSingleConnection( data, arr[j].node, e.target.classList[1],arr[j].output)
// e.target.remove();
// }
// }
// });
// }
for(let i = 0; i < output.length; i++ ){
output[i].addEventListener('contextmenu', function(e){
e.preventDefault();
e.stopPropagation()
// console.log(e.target)
//删除当前连接点前 如果有线段连接则去除
// e.target.remove();
});
}
}
......
......@@ -994,6 +994,31 @@
h.style.left = i + "px",
r.appendChild(h),
this.precanvas.appendChild(r);
// console.log($(".attrs"))
// console.log($(".attrs").attr("attr_left"))
// console.log($(".attrs").attr("attr_right"))
// $(".attrs").each(function(item) {
// console.log(item)
// var e = $(this).attr("attr_left");
// var t = $(this).attr("attr_right");
// });
const arr_input = $(".attrs").parents().parents().parents().parents().find(".inputs").children()
const arr_output = $(".attrs").parents().parents().parents().parents().find(".outputs").children()
console.log(e)
console.log(arr_input)
arr_input.each(function(item){
console.log($(this))
if($(this).find(".label_left").length == 0){
$(this).append(`<label class='label_left'>条件${item}</label>`)
}
})
arr_output.each(function(item){
console.log($(this).find(".label_right"))
if($(this).find(".label_right").length == 0){
$(this).append(`<label class='label_right'>${(item+1)%2==0?'满足':'不满足'}</label>`)
}
})
var w = {
id: a,
name: e,
......
......@@ -177,10 +177,11 @@ function handleContextmenu(e) {
// 阻止默认右键菜单
e.preventDefault()
e.stopPropagation()
console.log(e)
// console.log(e)
//判断当前的线段关闭功能是否显示
if(document.getElementsByClassName('drawflow-delete').length > 0){
document.getElementById('customContextMenu').style.display = 'none';
hideMenu()
return
}
const customMenu = document.getElementById('customContextMenu');
......@@ -221,6 +222,7 @@ function handleContextmenu(e) {
// console.log(`文档坐标:(${x}, ${y})`);
// }
// 右键菜单
......@@ -237,6 +239,7 @@ function rightMenu() {
// 如果点击的不是菜单,则隐藏菜单
if (!customMenu.contains(e.target)) {
customMenu.style.display = 'none';
// hideMenu()
}
});
......@@ -244,7 +247,9 @@ function rightMenu() {
const menuItems = customMenu.querySelectorAll('.menu-item');
menuItems.forEach(item => {
item.addEventListener('click', (event) => {
event.stopPropagation();
const action = item.getAttribute('data-action');
console.log(action)
// 根据不同的动作执行不同的操作
switch (action) {
case 'startCard':
......@@ -253,33 +258,22 @@ function rightMenu() {
case 'eventCard':
addNodeToDrawFlow_A("template",x,y)
break;
case 'conditionCard':
addNodeToDrawFlow_A("dbclick",x,y)
break;
case 'conditionCard-huo':
addNodeToDrawFlow_A("dbclick",x,y,'conditionCard-huo')
break;
case 'conditionCard-yu':
addNodeToDrawFlow_A("dbclick",x,y,'conditionCard-yu')
break;
case 'conditionCard-fei':
addNodeToDrawFlow_A("dbclick",x,y,'conditionCard-fei')
break;
case 'endCard':
addNodeToDrawFlow_A("slack",x,y)
break;
// case 'new':
// alert('您选择了 "新建文件"');
// break;
// case 'open':
// alert('您选择了 "打开"');
// break;
// case 'save':
// alert('您选择了 "保存"');
// break;
// case 'copy':
// alert('您选择了 "复制"');
// break;
// case 'paste':
// alert('您选择了 "粘贴"');
// break;
// case 'refresh':
// alert('页面即将刷新...');
// setTimeout(() => location.reload(), 500);
// break;
// case 'info':
// alert('自定义右键菜单 v1.0\n© 2023 前端开发示例');
// break;
}
// 点击菜单项后隐藏菜单
customMenu.style.display = 'none';
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment