2022-12-22 06:57:51 +00:00
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="en">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
|
|
|
|
|
|
|
|
<!-- Bootstrap 的 CSS 文件 -->
|
|
|
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" crossorigin="anonymous">
|
|
|
|
|
|
|
|
|
|
<title>十字导航</title>
|
|
|
|
|
|
|
|
|
|
<style type="text/css">
|
|
|
|
|
*{
|
|
|
|
|
moz-user-select: -moz-none;
|
|
|
|
|
-moz-user-select: none;
|
|
|
|
|
-o-user-select:none;
|
|
|
|
|
-khtml-user-select:none;
|
|
|
|
|
-webkit-user-select:none;
|
|
|
|
|
-ms-user-select:none;
|
|
|
|
|
user-select:none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@font-face {
|
|
|
|
|
font-family: 'iconfont'; /* Project id 3145309 */
|
|
|
|
|
src: url('//at.alicdn.com/t/font_3145309_gmztz69c7.woff2?t=1642386884581') format('woff2'),
|
|
|
|
|
url('//at.alicdn.com/t/font_3145309_gmztz69c7.woff?t=1642386884581') format('woff'),
|
|
|
|
|
url('//at.alicdn.com/t/font_3145309_gmztz69c7.ttf?t=1642386884581') format('truetype');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.iconfont {
|
|
|
|
|
font-family: "iconfont" !important;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-style: normal;
|
|
|
|
|
-webkit-font-smoothing: antialiased;
|
|
|
|
|
-moz-osx-font-smoothing: grayscale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#canvas canvas {
|
|
|
|
|
border: 1px dotted black
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tooltip-inner{
|
|
|
|
|
max-width: 400px !important;
|
|
|
|
|
text-align: justify;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="container" style="text-align: center">
|
|
|
|
|
|
|
|
|
|
<div class="head" style="position: absolute; top: 2rem; right: 2rem">
|
|
|
|
|
<div class="btn-group" role="group">
|
|
|
|
|
<button onclick="addObj()" type="button" class="btn btn-primary"><span class="iconfont"></span>添加</button>
|
|
|
|
|
<button onclick="clearObjs()" type="button" class="btn btn-danger"><span class="iconfont"></span>清空</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<button type="button" class="btn btn-info" data-toggle="tooltip" data-placement="bottom" data-html="true"
|
|
|
|
|
title="</br><ol><li>点击【添加】画板中会添加一个默认事件</li><li>右键事件可以修改</li><li>将事件修改为空会完全删除事件</li><li>刷新页面会丢失所有数据</li></ol>">帮助</button>
|
|
|
|
|
|
2023-08-09 05:57:49 +00:00
|
|
|
|
<div class="dropdown" style="display: inline-block">
|
|
|
|
|
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
|
|
|
|
|
选色 <div id="color" style="display: inline-block; width: 0.8rem; height: 0.8rem; background: red">
|
|
|
|
|
</button>
|
|
|
|
|
<div class="dropdown-menu">
|
|
|
|
|
<a class="dropdown-item" href="#" onclick="setColor(0xFF0000)">红 <div style="display: inline-block; width: 20px; height: 0.8rem; background: red"></div></a>
|
|
|
|
|
<a class="dropdown-item" href="#" onclick="setColor(0xFFBB00)">橙 <div style="display: inline-block; width: 20px; height: 0.8rem; background: orange"></div></a>
|
|
|
|
|
<a class="dropdown-item" href="#" onclick="setColor(0x009FCC)">蓝 <div style="display: inline-block; width: 20px; height: 0.8rem; background: blue"></div></a>
|
|
|
|
|
<a class="dropdown-item" href="#" onclick="setColor(0x00FF00)">绿 <div style="display: inline-block; width: 20px; height: 0.8rem; background: green"></div></a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2022-12-22 06:57:51 +00:00
|
|
|
|
<div class="btn-group" role="group">
|
|
|
|
|
<button onclick="imports()" type="button" class="btn btn-primary"><span class="iconfont"></span>导入
|
|
|
|
|
<input style="display: none" type="file" accept=".crossnav.png" class="custom-file-input" id="custom-file-input">
|
|
|
|
|
</button>
|
|
|
|
|
<button onclick="outports()" type="button" class="btn btn-primary"><span class="iconfont"></span>导出</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div id="canvas" style="margin-top: 5rem;">
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 图片 exif 操作 -->
|
|
|
|
|
<script src="./exif.js"></script>
|
|
|
|
|
|
|
|
|
|
<!-- 选项 1:jQuery 和 Bootstrap 集成包(集成了 Popper) -->
|
|
|
|
|
<script src="./jquery.slim.min.js" crossorigin="anonymous"></script>
|
|
|
|
|
<script src="./bootstrap.bundle.min.js" crossorigin="anonymous"></script>
|
|
|
|
|
|
|
|
|
|
<!-- 动画库 -->
|
2023-08-09 05:57:49 +00:00
|
|
|
|
<script src="./pixi.min.js"></script>
|
|
|
|
|
<script src="./PIXI.TextInput.min.js"></script>
|
2022-12-22 06:57:51 +00:00
|
|
|
|
|
2023-08-09 05:57:49 +00:00
|
|
|
|
<script src="./png.bundle.js"></script>
|
2022-12-22 06:57:51 +00:00
|
|
|
|
|
|
|
|
|
<script type="application/javascript">
|
|
|
|
|
document.oncontextmenu = function(e){
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function newDelta(){
|
|
|
|
|
return 50 * (Math.random() - 0.5)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$(function () {
|
|
|
|
|
$('[data-toggle="tooltip"]').tooltip()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
<script type="application/javascript">
|
2023-08-09 05:57:49 +00:00
|
|
|
|
|
|
|
|
|
function setColor( c ){
|
|
|
|
|
color = c;
|
|
|
|
|
var hex = c.toString(16);
|
|
|
|
|
if( hex.length < 6 ) {
|
|
|
|
|
hex = "000000" + hex
|
|
|
|
|
hex = hex.substr( hex.length -6 );
|
|
|
|
|
}
|
|
|
|
|
$("#color").css({ background : "#" + hex })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var color = 0xFF0000 ;
|
|
|
|
|
|
2022-12-22 06:57:51 +00:00
|
|
|
|
var border = 20;
|
|
|
|
|
var size = 512 + 2 * border; // 10 的边框
|
|
|
|
|
//Create a Pixi Application
|
|
|
|
|
var app = new PIXI.Application({width: size, height: size});
|
|
|
|
|
//Add the canvas that Pixi automatically created for you to the HTML document
|
|
|
|
|
document.getElementById("canvas").appendChild(app.view);
|
|
|
|
|
|
|
|
|
|
var bg = new PIXI.Container();
|
|
|
|
|
bg.x = 0;
|
|
|
|
|
bg.y = 0;
|
|
|
|
|
app.stage.addChild(bg);
|
|
|
|
|
|
|
|
|
|
var rectangle = new PIXI.Graphics();
|
|
|
|
|
rectangle.beginFill(0xFFFFFF);
|
|
|
|
|
rectangle.drawRect(0, 0, app.renderer.view.width, app.renderer.view.height);
|
|
|
|
|
rectangle.endFill();
|
|
|
|
|
bg.addChild( rectangle )
|
|
|
|
|
|
|
|
|
|
var xyStyle = new PIXI.TextStyle({
|
|
|
|
|
fontFamily: "Arial",
|
|
|
|
|
fontSize: 18,
|
|
|
|
|
fill: "blank"
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// x 轴
|
|
|
|
|
var lineX = new PIXI.Graphics();
|
|
|
|
|
lineX.lineStyle(2, 0x000000, 1);
|
|
|
|
|
lineX.moveTo( border, size /2);
|
|
|
|
|
lineX.lineTo( size - border, size /2);
|
|
|
|
|
bg.addChild(lineX);
|
|
|
|
|
|
|
|
|
|
// x 轴方向
|
|
|
|
|
var triangle = new PIXI.Graphics();
|
|
|
|
|
var baseX = size - border;
|
|
|
|
|
var baseY = size /2;
|
|
|
|
|
triangle.beginFill(0x000000);
|
|
|
|
|
//Use `drawPolygon` to define the triangle as
|
|
|
|
|
//a path array of x/y positions
|
|
|
|
|
triangle.drawPolygon([
|
|
|
|
|
baseX , baseY + 5, //First point
|
|
|
|
|
baseX , baseY - 5, //Second point
|
|
|
|
|
baseX + 8, baseY + 0 //Third point
|
|
|
|
|
]);
|
|
|
|
|
//Fill shape's color
|
|
|
|
|
triangle.endFill();
|
|
|
|
|
bg.addChild(triangle);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var message = new PIXI.Text("紧急", xyStyle);
|
|
|
|
|
message.position.set(baseX - 30 , baseY + 10 );
|
|
|
|
|
bg.addChild(message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// y 轴
|
|
|
|
|
var lineX = new PIXI.Graphics();
|
|
|
|
|
lineX.lineStyle(2, 0x000000, 1);
|
|
|
|
|
lineX.moveTo( size /2, border );
|
|
|
|
|
lineX.lineTo( size /2 , size - border);
|
|
|
|
|
bg.addChild(lineX);
|
|
|
|
|
|
|
|
|
|
// x 轴方向
|
|
|
|
|
var triangle = new PIXI.Graphics();
|
|
|
|
|
var baseX = size / 2;
|
|
|
|
|
var baseY = border;
|
|
|
|
|
triangle.beginFill(0x000000);
|
|
|
|
|
//Use `drawPolygon` to define the triangle as
|
|
|
|
|
//a path array of x/y positions
|
|
|
|
|
triangle.drawPolygon([
|
|
|
|
|
baseX + 5, baseY , //First point
|
|
|
|
|
baseX - 5, baseY , //Second point
|
|
|
|
|
baseX, baseY - 8 //Third point
|
|
|
|
|
]);
|
|
|
|
|
//Fill shape's color
|
|
|
|
|
triangle.endFill();
|
|
|
|
|
bg.addChild(triangle);
|
|
|
|
|
|
|
|
|
|
var message = new PIXI.Text("重要", xyStyle);
|
|
|
|
|
message.position.set(baseX - 40 , baseY );
|
|
|
|
|
bg.addChild(message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var objs = new PIXI.Container();
|
|
|
|
|
app.stage.addChild(objs);
|
|
|
|
|
|
2023-08-09 05:57:49 +00:00
|
|
|
|
function newObj(x, y, name, c){
|
|
|
|
|
|
|
|
|
|
var objStyle = new PIXI.TextStyle({
|
|
|
|
|
fontFamily: "Arial",
|
|
|
|
|
fontSize: 18,
|
|
|
|
|
fill: c || color,
|
|
|
|
|
|
|
|
|
|
});
|
2022-12-22 06:57:51 +00:00
|
|
|
|
|
|
|
|
|
var obj = new PIXI.Container();
|
|
|
|
|
obj.backgroundColor = 0x1099bb;
|
|
|
|
|
obj.x = x;
|
|
|
|
|
obj.y = y;
|
|
|
|
|
objs.addChild(obj);
|
|
|
|
|
|
|
|
|
|
// point
|
|
|
|
|
var circle = new PIXI.Graphics();
|
2023-08-09 05:57:49 +00:00
|
|
|
|
circle.beginFill( c || color );
|
|
|
|
|
circle.drawCircle( 0, 0, 5 );
|
2022-12-22 06:57:51 +00:00
|
|
|
|
circle.endFill();
|
|
|
|
|
circle.position.set(0 , 0 );
|
|
|
|
|
obj.addChild(circle);
|
|
|
|
|
|
|
|
|
|
var message = new PIXI.Text(name, objStyle);
|
|
|
|
|
message.position.set( 8 , - 10);
|
|
|
|
|
message.name = 'message'
|
|
|
|
|
obj.addChild(message);
|
|
|
|
|
|
|
|
|
|
var input = new PIXI.TextInput({
|
|
|
|
|
input: objStyle,
|
|
|
|
|
box: {
|
|
|
|
|
default: {fill: 0xE8E9F3, rounded: 12, stroke: {color: 0xCBCEE0, width: 3}},
|
|
|
|
|
focused: {fill: 0xE1E3EE, rounded: 12, stroke: {color: 0xABAFC6, width: 3}},
|
|
|
|
|
disabled: {fill: 0xDBDBDB, rounded: 12}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
input.position.set(0 + 8 , 0 - 10);
|
2023-08-09 05:57:49 +00:00
|
|
|
|
input.placeholder = '输入...'
|
2022-12-22 06:57:51 +00:00
|
|
|
|
input.visible = false
|
|
|
|
|
input.maxLength = 20
|
|
|
|
|
input.on('keydown', function (keycode) {
|
|
|
|
|
console.log('key pressed:', keycode)
|
|
|
|
|
if ( 13 === keycode ) {
|
|
|
|
|
endEdit()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
input.on('blur', function () {
|
|
|
|
|
console.log( "blur" )
|
|
|
|
|
endEdit()
|
|
|
|
|
})
|
2023-08-09 05:57:49 +00:00
|
|
|
|
|
2022-12-22 06:57:51 +00:00
|
|
|
|
function endEdit(){
|
|
|
|
|
input.visible = false
|
|
|
|
|
message.visible = true
|
2023-08-09 05:57:49 +00:00
|
|
|
|
|
2022-12-22 06:57:51 +00:00
|
|
|
|
if ( input.text ) {
|
|
|
|
|
message.text = input.text
|
|
|
|
|
} else {
|
2023-08-09 05:57:49 +00:00
|
|
|
|
objs.removeChild(obj);
|
2022-12-22 06:57:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
obj.addChild(input);
|
|
|
|
|
|
|
|
|
|
// 实现头像拖动
|
|
|
|
|
obj.interactive = true; //设置为可交互的
|
|
|
|
|
|
|
|
|
|
obj
|
|
|
|
|
.on('touchstart', onDragStart)
|
|
|
|
|
.on('touchend', onDragEnd)
|
|
|
|
|
.on('touchmove', onDragMove)
|
|
|
|
|
.on('mousedown', onDragStart )
|
|
|
|
|
.on('mouseup', onDragEnd)
|
|
|
|
|
.on('mouseupoutside', onDragEnd)
|
|
|
|
|
.on('mousemove', onDragMove)
|
|
|
|
|
.on("rightclick", function (event) {
|
|
|
|
|
input.visible = true
|
|
|
|
|
message.visible = false
|
|
|
|
|
input.placeholder = "输入事件名称,回车确认,为空则删除整个事件。"
|
|
|
|
|
input.text = message.text
|
|
|
|
|
input.focus();
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function onDragStart(event) {
|
|
|
|
|
this.data = event.data;
|
|
|
|
|
this.alpha = 0.5;
|
|
|
|
|
this.dragging = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onDragEnd() {
|
|
|
|
|
this.alpha = 1;
|
|
|
|
|
this.dragging = false;
|
|
|
|
|
this.data = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onDragMove(event) {
|
|
|
|
|
if (this.dragging) {
|
|
|
|
|
this.position = this.data.getLocalPosition(this.parent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script type="application/javascript">
|
|
|
|
|
|
|
|
|
|
function addObj(){
|
|
|
|
|
var x = size /4 + newDelta()
|
|
|
|
|
var y = size /4 + newDelta()
|
|
|
|
|
newObj(x, y, "新建事件")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearObjs(){
|
|
|
|
|
objs.removeChildren()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function imports(){
|
|
|
|
|
var oFlieImg = document.getElementById("custom-file-input");
|
|
|
|
|
oFlieImg.onchange = function(e){
|
|
|
|
|
var _self = e.currentTarget;
|
|
|
|
|
var oSelfFile = _self.files[0]; //获取文件
|
|
|
|
|
|
|
|
|
|
// console.log(oSelfFile.name.lastIndexOf('.'));
|
|
|
|
|
// 如果要限制文件类型的话这里可以判定oSelfFile.name‘.’最后一次出现的位置之后的单词是否为想要的类型
|
|
|
|
|
// 或者判断oSelfFile.type
|
|
|
|
|
// 判断文件大小为size单位为字节
|
|
|
|
|
var oReader = new FileReader();
|
|
|
|
|
oReader.readAsDataURL(oSelfFile); // 读取文件
|
|
|
|
|
// 加载文件
|
|
|
|
|
oReader.onload = function(ev){
|
|
|
|
|
// 获取到FileReader读取文件的base64
|
|
|
|
|
var oImgBase64 = ev.currentTarget.result;
|
|
|
|
|
// console.log(oImgBase64)
|
|
|
|
|
|
|
|
|
|
var meta = png.de( oImgBase64 );
|
|
|
|
|
try {
|
|
|
|
|
var json = meta.crossnav
|
|
|
|
|
json = JSON.parse( json )
|
|
|
|
|
json.map(function (a){
|
2023-08-09 05:57:49 +00:00
|
|
|
|
newObj(a.x, a.y, a.text, a.color)
|
2022-12-22 06:57:51 +00:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
}catch ( e ) {
|
|
|
|
|
alert("导入错误 " + e)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oFlieImg.click();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function outports(){
|
|
|
|
|
var img = app.renderer.plugins.extract.base64(app.stage);
|
|
|
|
|
let a = document.createElement("a"); // 生成一个a元素
|
|
|
|
|
let event = new MouseEvent("click"); // 创建一个单击事件
|
|
|
|
|
a.download = (new Date()).toLocaleString() + ".crossnav.png"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let info = []
|
|
|
|
|
for (let c of objs.children) {
|
2023-08-09 05:57:49 +00:00
|
|
|
|
|
|
|
|
|
var t = c.getChildByName('message')
|
|
|
|
|
|
2022-12-22 06:57:51 +00:00
|
|
|
|
info.push({
|
|
|
|
|
x : c.x,
|
|
|
|
|
y : c.y,
|
2023-08-09 05:57:49 +00:00
|
|
|
|
text : t.text,
|
|
|
|
|
color : t.style.fill
|
2022-12-22 06:57:51 +00:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
img = png.en( img, {
|
|
|
|
|
"crossnav" : JSON.stringify( info )
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
a.href = img; // 将生成的URL设置为a.href属性
|
|
|
|
|
a.dispatchEvent(event); // 触发a的单击事件
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|