Compare commits
3 Commits
c1ff893b58
...
42ddd0fcdb
Author | SHA1 | Date |
---|---|---|
|
42ddd0fcdb | |
|
2b5154062d | |
|
4465091db3 |
|
@ -36,4 +36,13 @@ public class CommonTest
|
||||||
};
|
};
|
||||||
Assert.Equal(Number.ReverseBytes(bytesArray, 4).Value, rev4Bytes);
|
Assert.Equal(Number.ReverseBytes(bytesArray, 4).Value, rev4Bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToBitTest()
|
||||||
|
{
|
||||||
|
Assert.Equal(Number.ToBit(0xFF, 3).Value, true);
|
||||||
|
Assert.Equal(Number.ToBit(0x00, 3).Value, false);
|
||||||
|
Assert.Equal(Number.ToBit(0xAA, 3).Value, true);
|
||||||
|
Assert.Equal(Number.ToBit(0xAA, 2).Value, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ try
|
||||||
|
|
||||||
// Services Settings
|
// Services Settings
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
builder.Services.AddControllersWithViews();
|
// builder.Services.AddControllersWithViews();
|
||||||
|
|
||||||
// NLog: Setup NLog for Dependency injection
|
// NLog: Setup NLog for Dependency injection
|
||||||
builder.Logging.ClearProviders();
|
builder.Logging.ClearProviders();
|
||||||
|
|
|
@ -158,7 +158,7 @@ namespace Common
|
||||||
return new(new ArgumentException(
|
return new(new ArgumentException(
|
||||||
"Location can't be negetive", nameof(location)));
|
"Location can't be negetive", nameof(location)));
|
||||||
|
|
||||||
return (srcBits & (1 << location)) == 1;
|
return ((srcBits >> location) & ((UInt32)0b1)) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -217,8 +217,8 @@ public class JtagController : ControllerBase
|
||||||
return TypedResults.Ok(new
|
return TypedResults.Ok(new
|
||||||
{
|
{
|
||||||
original = ret.Value,
|
original = ret.Value,
|
||||||
binary = binaryValue,
|
binaryValue,
|
||||||
decode = decodeValue,
|
decodeValue,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -291,6 +291,7 @@ public class JtagController : ControllerBase
|
||||||
|
|
||||||
// 定义缓冲区大小: 32KB
|
// 定义缓冲区大小: 32KB
|
||||||
byte[] buffer = new byte[32 * 1024];
|
byte[] buffer = new byte[32 * 1024];
|
||||||
|
byte[] revBuffer = new byte[32 * 1024];
|
||||||
long totalBytesRead = 0;
|
long totalBytesRead = 0;
|
||||||
|
|
||||||
// 使用异步流读取文件
|
// 使用异步流读取文件
|
||||||
|
@ -299,12 +300,17 @@ public class JtagController : ControllerBase
|
||||||
int bytesRead;
|
int bytesRead;
|
||||||
while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
||||||
{
|
{
|
||||||
var revBuffer = Common.Number.ReverseBytes(buffer, 4);
|
// 反转 32bits
|
||||||
|
var retBuffer = Common.Number.ReverseBytes(buffer, 4);
|
||||||
|
if (!retBuffer.IsSuccessful)
|
||||||
|
return TypedResults.InternalServerError(retBuffer.Error);
|
||||||
|
revBuffer = retBuffer.Value;
|
||||||
|
for (int i = 0; i < buffer.Length; i++)
|
||||||
|
{
|
||||||
|
revBuffer[i] = BinaryPrimitives.ReverseEndianness(revBuffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
if (!revBuffer.IsSuccessful)
|
await memoryStream.WriteAsync(revBuffer, 0, bytesRead);
|
||||||
return TypedResults.InternalServerError(revBuffer.Error);
|
|
||||||
|
|
||||||
await memoryStream.WriteAsync(revBuffer.Value, 0, bytesRead);
|
|
||||||
totalBytesRead += bytesRead;
|
totalBytesRead += bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -222,107 +222,107 @@ public class JtagStatusReg
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ID 错误标志
|
/// ID 错误标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool id_err;
|
public bool id_err { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// CRC 错误标志
|
/// CRC 错误标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool crc_err;
|
public bool crc_err { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自动测试错误标志
|
/// 自动测试错误标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool aut_err;
|
public bool aut_err { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 回读 CRC 错误标志
|
/// 回读 CRC 错误标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool rbcrc_err;
|
public bool rbcrc_err { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 超时标志
|
/// 超时标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool timeout;
|
public bool timeout { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 唤醒完成标志
|
/// 唤醒完成标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool wakeup_over;
|
public bool wakeup_over { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 休眠完成标志
|
/// 休眠完成标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool wakedown_over;
|
public bool wakedown_over { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 模式位
|
/// 模式位
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte m;
|
public string m { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化完成标志
|
/// 初始化完成标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool init_complete;
|
public bool init_complete { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化状态(低电平有效)
|
/// 初始化状态(低电平有效)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool init_n;
|
public bool init_n { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 完成标志
|
/// 完成标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool done;
|
public bool done { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 内部完成标志
|
/// 内部完成标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool done_i;
|
public bool done_i { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 全局逻辑使能标志
|
/// 全局逻辑使能标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool glogen;
|
public bool glogen { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 全局逻辑反馈标志
|
/// 全局逻辑反馈标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool glogen_fb;
|
public bool glogen_fb { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 全局输出使能标志
|
/// 全局输出使能标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool gouten;
|
public bool gouten { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 全局复位标志
|
/// 全局复位标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool grsn;
|
public bool grsn { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 全局写使能标志
|
/// 全局写使能标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool gwen;
|
public bool gwen { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PLL 锁定标志
|
/// PLL 锁定标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool pll_lock;
|
public bool pll_lock { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 回退标志
|
/// 回退标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool fallback;
|
public bool fallback { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IPAL 模式位
|
/// IPAL 模式位
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte ipal_m;
|
public string ipal_m { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 8 位标志
|
/// 8 位标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool flg_x8;
|
public bool flg_x8 { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 16 位标志
|
/// 16 位标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool flg_x16;
|
public bool flg_x16 { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 32 位标志
|
/// 32 位标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool flg_x32;
|
public bool flg_x32 { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 过温标志
|
/// 过温标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool over_temp;
|
public bool over_temp { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 配置错误标志
|
/// 配置错误标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool prcfg_err;
|
public bool prcfg_err { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 配置完成标志
|
/// 配置完成标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool prcfg_over;
|
public bool prcfg_over { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造函数,从 32 位代码解析 JTAG 状态寄存器
|
/// 构造函数,从 32 位代码解析 JTAG 状态寄存器
|
||||||
|
@ -337,7 +337,7 @@ public class JtagStatusReg
|
||||||
this.timeout = Common.Number.ToBit(code, 4).Value;
|
this.timeout = Common.Number.ToBit(code, 4).Value;
|
||||||
this.wakeup_over = Common.Number.ToBit(code, 5).Value;
|
this.wakeup_over = Common.Number.ToBit(code, 5).Value;
|
||||||
this.wakedown_over = Common.Number.ToBit(code, 6).Value;
|
this.wakedown_over = Common.Number.ToBit(code, 6).Value;
|
||||||
this.m = ((byte)(code & (0b111 << 7)));
|
this.m = Convert.ToString(((code >> 7) & 0b111), 2);
|
||||||
this.init_complete = Common.Number.ToBit(code, 10).Value;
|
this.init_complete = Common.Number.ToBit(code, 10).Value;
|
||||||
this.init_n = Common.Number.ToBit(code, 11).Value;
|
this.init_n = Common.Number.ToBit(code, 11).Value;
|
||||||
this.done = Common.Number.ToBit(code, 12).Value;
|
this.done = Common.Number.ToBit(code, 12).Value;
|
||||||
|
@ -349,7 +349,7 @@ public class JtagStatusReg
|
||||||
this.gwen = Common.Number.ToBit(code, 18).Value;
|
this.gwen = Common.Number.ToBit(code, 18).Value;
|
||||||
this.pll_lock = Common.Number.ToBit(code, 19).Value;
|
this.pll_lock = Common.Number.ToBit(code, 19).Value;
|
||||||
this.fallback = Common.Number.ToBit(code, 21).Value;
|
this.fallback = Common.Number.ToBit(code, 21).Value;
|
||||||
this.ipal_m = ((byte)(code & (0b11 << 22)));
|
this.ipal_m = Convert.ToString(((code >> 22) & 0b11), 2);
|
||||||
this.flg_x8 = Common.Number.ToBit(code, 24).Value;
|
this.flg_x8 = Common.Number.ToBit(code, 24).Value;
|
||||||
this.flg_x16 = Common.Number.ToBit(code, 25).Value;
|
this.flg_x16 = Common.Number.ToBit(code, 25).Value;
|
||||||
this.flg_x32 = Common.Number.ToBit(code, 26).Value;
|
this.flg_x32 = Common.Number.ToBit(code, 26).Value;
|
||||||
|
@ -887,6 +887,12 @@ public class Jtag
|
||||||
if (!ret.IsSuccessful) return new(ret.Error);
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) return new(new Exception("Jtag IDLE Delay Failed"));
|
else if (!ret.Value) return new(new Exception("Jtag IDLE Delay Failed"));
|
||||||
|
|
||||||
|
var retCode = await ReadStatusReg();
|
||||||
|
if (!retCode.IsSuccessful) return new(retCode.Error);
|
||||||
|
var jtagStatus = new JtagStatusReg(retCode.Value);
|
||||||
|
if (!(jtagStatus.done && jtagStatus.wakeup_over && jtagStatus.init_complete))
|
||||||
|
return new(new Exception("Jtag download bitstream failed"));
|
||||||
|
|
||||||
ret = await CloseTest();
|
ret = await CloseTest();
|
||||||
if (!ret.IsSuccessful) return new(ret.Error);
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));
|
else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));
|
||||||
|
|
|
@ -1,37 +1,52 @@
|
||||||
<template>
|
<template>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" :width="props.width" :height="props.height" viewBox="0 0 1600 1600">
|
<div class="relative" :style="{width: `${props.width}px`, height: `${props.height}px`}">
|
||||||
<def>
|
<!-- 简化的SVG按钮 -->
|
||||||
<filter id="shadow" x="-50%" y="-50%" width="200%" height="200%">
|
<svg xmlns="http://www.w3.org/2000/svg" :width="props.width" :height="props.height" viewBox="0 0 1600 1600">
|
||||||
<feGaussianBlur in="SourceAlpha" stdDeviation="20" result="blur" />
|
<defs>
|
||||||
<feColorMatrix result="bluralpha" type="matrix" :values="colorMatrix" />
|
<filter id="btn-shadow">
|
||||||
<feOffset in="bluralpha" dx="20" dy="20" result="offsetBlur" />
|
<feGaussianBlur in="SourceAlpha" stdDeviation="20" result="blur" />
|
||||||
<feMerge>
|
<feColorMatrix result="bluralpha" type="matrix" :values="colorMatrix" />
|
||||||
<feMergeNode in="offsetBlur" />
|
<feOffset in="bluralpha" dx="20" dy="20" result="offsetBlur" />
|
||||||
<feMergeNode in="SourceGraphic" />
|
<feMerge>
|
||||||
</feMerge>
|
<feMergeNode in="offsetBlur" />
|
||||||
</filter>
|
<feMergeNode in="SourceGraphic" />
|
||||||
</def>
|
</feMerge>
|
||||||
<g>
|
</filter>
|
||||||
|
<linearGradient id="normal" gradientTransform="rotate(45 0 0)">
|
||||||
|
<stop stop-color="#4b4b4b" offset="0" />
|
||||||
|
<stop stop-color="#171717" offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="pressed" gradientTransform="rotate(45 0 0)">
|
||||||
|
<stop stop-color="#171717" offset="0" />
|
||||||
|
<stop stop-color="#4b4b4b" offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- 按钮底座 -->
|
||||||
<rect width="800" height="800" x="400" y="400" fill="#464646" rx="20" />
|
<rect width="800" height="800" x="400" y="400" fill="#464646" rx="20" />
|
||||||
<rect width="700" height="700" x="450" y="450" fill="#eaeaea" rx="20" />
|
<rect width="700" height="700" x="450" y="450" fill="#eaeaea" rx="20" />
|
||||||
|
|
||||||
|
<!-- 装饰螺丝 -->
|
||||||
<circle r="20" cx="1075" cy="1075" fill="#171717" />
|
<circle r="20" cx="1075" cy="1075" fill="#171717" />
|
||||||
<circle r="20" cx="1075" cy="525" fill="#171717" />
|
<circle r="20" cx="1075" cy="525" fill="#171717" />
|
||||||
<circle r="20" cx="525" cy="525" fill="#171717" />
|
<circle r="20" cx="525" cy="525" fill="#171717" />
|
||||||
<circle r="20" cx="525" cy="1075" fill="#171717" />
|
<circle r="20" cx="525" cy="1075" fill="#171717" />
|
||||||
</g>
|
|
||||||
<g>
|
<!-- 按钮主体 -->
|
||||||
<linearGradient id="normal" gradientTransform="rotate(45 0 0)">
|
<circle r="220" cx="800" cy="800" fill="black" filter="url(#btn-shadow)" />
|
||||||
<stop stop-color="#4b4b4b" offset="0" />
|
<circle
|
||||||
<stop stop-color="#171717" offset="1" />
|
:r="btnHeight"
|
||||||
</linearGradient>
|
cx="800"
|
||||||
<linearGradient id="pressed" gradientTransform="rotate(45 0 0)">
|
cy="800"
|
||||||
<stop stop-color="#171717" offset="0" />
|
:fill="isKeyPressed ? 'url(#pressed)' : 'url(#normal)'"
|
||||||
<stop stop-color="#4b4b4b" offset="1" />
|
fill-opacity="0.9"
|
||||||
</linearGradient>
|
@mousedown="toggleButtonState(true)"
|
||||||
<circle class="shadow" r="220" cx="800" cy="800" fill="black" />
|
@mouseup="toggleButtonState(false)"
|
||||||
<circle class="light" @mousedown="toggleButtonState(true)" @mouseup="toggleButtonState(false)"
|
@contextmenu.prevent="openContextMenu($event)"
|
||||||
@contextmenu.prevent="openContextMenu($event)" :r="btnHeight" cx="800" cy="800"
|
style="pointer-events: auto; transition: all 20ms ease-in-out;"
|
||||||
fill-opacity="0.9" style="pointer-events: auto;"/>
|
/>
|
||||||
|
|
||||||
|
<!-- 按键文字 -->
|
||||||
<text
|
<text
|
||||||
v-if="bindKey"
|
v-if="bindKey"
|
||||||
x="800"
|
x="800"
|
||||||
|
@ -40,20 +55,23 @@
|
||||||
text-anchor="middle"
|
text-anchor="middle"
|
||||||
dominant-baseline="central"
|
dominant-baseline="central"
|
||||||
fill="#ccc"
|
fill="#ccc"
|
||||||
style="font-family: Arial; filter: url(#shadow); user-select: none; pointer-events: none; mix-blend-mode: overlay;"
|
style="font-family: Arial; filter: url(#btn-shadow); user-select: none; pointer-events: none; mix-blend-mode: overlay;"
|
||||||
>
|
>
|
||||||
{{ bindKey.toUpperCase() }}
|
{{ bindKey.toUpperCase() }}
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</svg>
|
||||||
</svg>
|
|
||||||
<div v-if="showContextMenu"
|
<!-- 使用DaisyUI的卡片组件实现上下文菜单 -->
|
||||||
:style="{ top: contextMenuY + 'px', left: contextMenuX + 'px' }"
|
<div v-if="showContextMenu"
|
||||||
@click.stop
|
class="card card-compact fixed z-50 shadow-lg bg-base-100 border border-base-300"
|
||||||
class="fixed z-50 border border-base-300 bg-base-100 rounded-md shadow-lg">
|
:style="{ top: contextMenuY + 'px', left: contextMenuX + 'px' }"
|
||||||
<div class="px-4 py-2 cursor-pointer whitespace-nowrap text-base-content hover:bg-base-200"
|
@click.stop>
|
||||||
@click="startBinding">
|
<div class="card-body p-0">
|
||||||
<span v-if="isBinding">请输入</span>
|
<button class="btn btn-ghost justify-start normal-case w-full h-full" @click="startBinding">
|
||||||
<span v-else>绑定按键: {{ bindKey ? bindKey.toUpperCase() : '未绑定' }}</span>
|
<span v-if="isBinding">请输入</span>
|
||||||
|
<span v-else>绑定按键: {{ bindKey ? bindKey.toUpperCase() : '未绑定' }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -65,29 +83,28 @@ interface Props {
|
||||||
width?: string | number
|
width?: string | number
|
||||||
height?: string | number
|
height?: string | number
|
||||||
}
|
}
|
||||||
const bindKey = ref('');
|
|
||||||
let isKeyPressed = false;
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
width: 160,
|
width: 160,
|
||||||
height: 160,
|
height: 160,
|
||||||
})
|
})
|
||||||
|
|
||||||
const btnHeight = ref(200)
|
const bindKey = ref('');
|
||||||
|
let isKeyPressed = false;
|
||||||
const colorMatrix = ref("1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0")
|
const btnHeight = ref(200);
|
||||||
|
const colorMatrix = ref("1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0");
|
||||||
function toggleButtonState(isPressed: boolean) {
|
|
||||||
btnHeight.value = isPressed ? 210 : 200;
|
|
||||||
colorMatrix.value = isPressed
|
|
||||||
? "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.7 0"
|
|
||||||
: "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0";
|
|
||||||
}
|
|
||||||
|
|
||||||
const isBinding = ref(false);
|
const isBinding = ref(false);
|
||||||
const showContextMenu = ref(false);
|
const showContextMenu = ref(false);
|
||||||
const contextMenuX = ref(0);
|
const contextMenuX = ref(0);
|
||||||
const contextMenuY = ref(0);
|
const contextMenuY = ref(0);
|
||||||
|
|
||||||
|
function toggleButtonState(isPressed: boolean) {
|
||||||
|
btnHeight.value = isPressed ? 210 : 200;
|
||||||
|
colorMatrix.value = isPressed
|
||||||
|
? "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.7 0"
|
||||||
|
: "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0";
|
||||||
|
}
|
||||||
|
|
||||||
function openContextMenu(e: MouseEvent) {
|
function openContextMenu(e: MouseEvent) {
|
||||||
contextMenuX.value = e.clientX;
|
contextMenuX.value = e.clientX;
|
||||||
contextMenuY.value = e.clientY;
|
contextMenuY.value = e.clientY;
|
||||||
|
@ -135,21 +152,3 @@ onUnmounted(() => {
|
||||||
window.removeEventListener('click', closeContextMenu);
|
window.removeEventListener('click', closeContextMenu);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="postcss">
|
|
||||||
circle {
|
|
||||||
transition: all 20ms ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shadow {
|
|
||||||
filter: url(#shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
.light:active {
|
|
||||||
fill: url(#pressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
.light {
|
|
||||||
fill: url(#normal);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
Loading…
Reference in New Issue