feat: 图片标注功能右键功能问题处理

master
LCJ-MinYa 6 months ago
parent f5aaaabaf1
commit 1038f93007

@ -31,6 +31,11 @@
@click="changeImage('next')" @click="changeImage('next')"
><ArrowRightBold ><ArrowRightBold
/></el-icon> /></el-icon>
<!-- 自定义右键菜单 -->
<ul id="customContextMenu">
<li @click="saveCanvasAsImage"></li>
<li @click="copyCanvasToClipboard"></li>
</ul>
</div> </div>
</Teleport> </Teleport>
</template> </template>
@ -251,6 +256,62 @@ const initTuiImageEditor = () => {
// refreshImageShow() // refreshImageShow()
// refreshImageShowWithDelay(300, true); // refreshImageShowWithDelay(300, true);
/**
* canvas禁用右键功能
* 该组件默认有两层canvas第一层图片canvas在底部画布canvas在顶部需要禁用右键功能(如果不禁用会导致默认右键复制和保存的图片是画布这一层空白的图片)
* 再自定义右键功能实现图片下载和复制到剪贴板功能
*/
const canvas = document.querySelector('.upper-canvas');
const customContextMenu = document.querySelector('#customContextMenu');
canvas.addEventListener('contextmenu', (e) => {
console.log(customContextMenu);
e.preventDefault();
//
customContextMenu.style.display = 'block';
customContextMenu.style.left = e.pageX + 'px';
customContextMenu.style.top = e.pageY + 'px';
});
//
document.querySelector('.tui-image-editor-wrap').addEventListener('click', () => {
customContextMenu.style.display = 'none';
});
};
const saveCanvasAsImage = () => {
const canvas = document.querySelector('.lower-canvas');
const a = document.createElement('a');
a.href = canvas.toDataURL('image/jpeg');
a.download = new Date().getTime() + '.jpg';
a.click();
a.remove();
};
// iframe<iframe allow="clipboard-write"></iframe>使
const copyCanvasToClipboard = async () => {
const canvas = document.querySelector('.lower-canvas');
/**
问题的现象
在使用浏览器的剪贴板API的 write 方法尝试将JPEG图像写入剪贴板时我们可能会遇到这样的错误DOMException: Failed to execute 'write' on 'Clipboard': Type image/jpeg not supported on write.
问题的原因
这个错误的产生主要是因为 write 方法目前只支持 text/plain text/html MIME 类型这意味着你不能直接将JPEG图像写入剪贴板然而为什么浏览器的剪贴板API会有这样的限制呢
在深入浏览器的内部实现之前我们先来了解一下剪贴板API剪贴板API是浏览器提供的一种接口用于访问用户的剪贴板它的主要目的是为了提供一种简单一致的方式来读取和写入剪贴板数据
然而由于安全和隐私的考虑浏览器的剪贴板API并不允许直接访问剪贴板中的所有类型的数据例如它不允许访问剪贴板中的图像数据除非用户明确地进行了粘贴操作这就是为什么我们不能直接将JPEG图像写入剪贴板的原因
解决方案
那么我们应该如何解决这个问题呢一种可能的解决方案是将JPEG图像转换为PNG图像然后将其写入剪贴板这个方法可能不适用于所有浏览器因为不是所有浏览器都支持 clipboard.write 方法或 ClipboardItem 对象但是我将提供的代码已经在大多数现代浏览器中进行了测试并且可以正常工作
*/
// 使png,
const blob = await new Promise((resolve) => {
canvas.toBlob(resolve, 'image/png');
});
if (navigator.clipboard && navigator.clipboard.write) {
await navigator.clipboard.write([
new ClipboardItem({
'image/png': blob,
}),
]);
}
}; };
const addEventListenerFN = () => { const addEventListenerFN = () => {
@ -266,7 +327,8 @@ const handleClickOutside = (event) => {
if ( if (
getBtnDom('.save-btn').contains(event.target) || getBtnDom('.save-btn').contains(event.target) ||
getBtnDom('.left-btn').contains(event.target) || getBtnDom('.left-btn').contains(event.target) ||
getBtnDom('.right-btn').contains(event.target) getBtnDom('.right-btn').contains(event.target) ||
getBtnDom('#customContextMenu').contains(event.target)
) { ) {
return; return;
} }
@ -472,4 +534,27 @@ body > svg:last-of-type {
.tui-image-editor-container div.tui-colorpicker-clearfix { .tui-image-editor-container div.tui-colorpicker-clearfix {
display: none !important; display: none !important;
} }
#customContextMenu {
position: absolute;
display: none;
background-color: #fff;
padding: 10px 0;
border-radius: 5px;
li {
box-sizing: border-box;
cursor: pointer;
font-size: 14px;
color: #666;
width: 100%;
height: 30px;
line-height: 30px;
padding: 0 10px;
}
li:hover {
background-color: #f5f5f5;
}
}
</style> </style>

Loading…
Cancel
Save