feat: md-pin

This commit is contained in:
hypercross 2026-02-26 18:20:52 +08:00
parent f7eb116aa3
commit 4c3d83922f
2 changed files with 48 additions and 7 deletions

View File

@ -13,6 +13,8 @@ customElement("md-pin", { x: 0, y: 0 }, (props, { element }) => {
width: "0",
height: "0"
});
const [showToast, setShowToast] = createSignal(false);
const [toastMessage, setToastMessage] = createSignal("");
let pinContainer: HTMLSpanElement | undefined;
let targetImage: HTMLImageElement | undefined;
let resizeObserver: ResizeObserver | undefined;
@ -124,23 +126,63 @@ customElement("md-pin", { x: 0, y: 0 }, (props, { element }) => {
}
});
// 处理点击,报告坐标并复制到剪贴板
const handleClick = (e: MouseEvent) => {
e.preventDefault();
e.stopPropagation();
if (!targetImage) return;
const imgRect = targetImage.getBoundingClientRect();
// 计算点击位置相对于图片的百分比
const clickX = ((e.clientX - imgRect.left) / imgRect.width) * 100;
const clickY = ((e.clientY - imgRect.top) / imgRect.height) * 100;
// 四舍五入到整数
const x = Math.round(clickX);
const y = Math.round(clickY);
// 生成格式化的坐标字符串
const coordText = `:md-pin[${label || ''}]{x=${x} y=${y}}`;
// 复制到剪贴板
navigator.clipboard.writeText(coordText).then(() => {
setToastMessage(`已复制:${coordText}`);
setShowToast(true);
setTimeout(() => setShowToast(false), 2000);
}).catch(err => {
console.error('复制失败:', err);
});
};
return (
<span ref={pinContainer} class="md-pin-container" style={{ display: 'inline', position: containerStyle().position, top: containerStyle().top, left: containerStyle().left, width: containerStyle().width, height: containerStyle().height }}>
<span
ref={pinContainer}
class="md-pin-container"
style={{ display: 'inline', position: containerStyle().position, top: containerStyle().top, left: containerStyle().left, width: containerStyle().width, height: containerStyle().height }}
onClick={handleClick}
>
<Show when={visible() && targetImage}>
<span
class="md-pin absolute transform -translate-x-1/2 -translate-y-1/2 pointer-events-auto cursor-pointer
bg-red-500 text-white text-xs font-bold rounded-full w-6 h-6
bg-red-500 text-white text-xs font-bold rounded-full w-6 h-6
flex items-center justify-center shadow-lg
hover:bg-red-600 hover:scale-110 transition-all z-10"
style={{
left: position().left,
top: position().top
}}
title={label || '标记点'}
title={label || '点击复制坐标'}
>
{label || '📍'}
</span>
</Show>
<Show when={showToast()}>
<div class="fixed bottom-4 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white px-4 py-2 rounded shadow-lg text-sm z-50">
{toastMessage()}
</div>
</Show>
</span>
);
});

View File

@ -1,7 +1,6 @@
# todo
## App
## md-pin
- [ ] 增强`data-loader`的功能,允许其生成目录树以及标题结构
- [ ] 添加一个侧边栏组件,用于显示目录树
- [ ] 在导航里添加按钮用于呼出侧边栏目录
- [ ] 创建并注册:md-pin组件。
- [ ] 对于:md-pin[A]{x=100 y=200} 而言,其将定位上方最近的一张图片,并在指定坐标位置上显示`A`的pin。