PerfectVector
Bởi Irene Kim

Bỏ qua vùng SVG trong suốt khi nhận nhấp chuột Konva

Cho vùng ảnh SVG trong suốt bỏ qua nhấp chuột trong Konva. Thử vùng tương tác dựa trên bộ đệm, kiểm tra lỗ và nền, rồi dựng lại sau khi đổi nguồn.

14 phút đọc
Trên trang này

Để vùng trong suốt của Konva.Image bỏ qua nhấp chuột, chờ ảnh nguồn giải mã xong, gọi imageNode.cache(), rồi gọi imageNode.drawHitFromCache(0) và vẽ lại lớp. Alpha của cảnh đã lưu đệm, tức độ đục pixel, sau đó xác định pixel ảnh nào tham gia nhận diện điểm nhấp.

Nút ảnh thông thường có thể nhận sự kiện trên toàn hình chữ nhật, kể cả lỗ SVG rỗng. Hướng dẫn Image Events của Konva minh họa phương án dựa trên alpha. Bài này thử SVG tự tạo có lỗ đặt trên nền nhận nhấp riêng, để lỗ ngừng bắt nhấp của ảnh có đích thực bên dưới nhận chúng.

Cách này thay đổi vùng tương tác canvas. Nó không tạo nút Konva.Path chỉnh được từ SVG hoặc đổi quy tắc DOM SVG pointer-events.

Tách ảnh khỏi vùng nhận tương tác

Vùng nhận tương tác là vùng Konva dùng để chọn đích sự kiện. Hình của nó có thể khác thiết kế nhìn thấy. Với một số ứng dụng, đích chữ nhật rộng là chủ ý; với ứng dụng khác, lỗ trong suốt cần cho người dùng chọn đối tượng dưới.

Tương tác mong muốnĐiểm bắt đầu
Chọn toàn ảnh từ bất cứ chỗ nào trong hình chữ nhậtHành vi nhận tương tác Image mặc định
Cho pixel trong suốt đi đến nút bên dướiLưu đệm ảnh và dựng vùng tương tác từ alpha
Chỉnh hoặc gắn hành động độc lập vào từng vùng vectorChọn đường dẫn Konva riêng và xác định hành vi
Điều khiển đích con trỏ trong DOM SVG nội tuyếnDùng hướng dẫn SVG pointer-events riêng

Shape API hiện tại nhận số nguyên alphaThreshold từ 0 đến 255; mặc định là 0. Truyền số tại đây, không phải hàm gọi lại. Nó khác bộ lọc Threshold trực quan. Ví dụ dùng 0 với vùng trong đục hoàn toàn và lỗ trong suốt hoàn toàn; không xác định ngưỡng ưu tiên cho bóng mềm hoặc mép khử răng cưa.

1. Lưu hai đầu vào SVG đầy đủ

Tạo thư mục trống. Lưu biểu trưng có lỗ tự tạo này thành hollow.svg:

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="180" viewBox="0 0 240 180">
  <path fill="#315d6f" fill-rule="evenodd"
        d="M20 30 L180 20 L215 60 L195 150 L35 160 L10 110 Z
           M80 65 L145 55 L160 110 L95 125 Z"/>
</svg>

Đường con bên trong tạo lỗ theo quy tắc tô even-odd. Lưu cùng hình ngoài nhưng bỏ đường con đó thành filled.svg:

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="180" viewBox="0 0 240 180">
  <path fill="#315d6f" d="M20 30 L180 20 L215 60 L195 150 L35 160 L10 110 Z"/>
</svg>

Tệp thứ hai là đối chứng đổi nguồn. Nó tô vị trí trước đó trống. Không tệp nào chứa hình chữ nhật nền trắng hoặc bitmap nhúng.

2. Tải, lưu đệm và ghi lại đích thực

Ví dụ dùng Konva 10.9.0. Lưu ba tệp này cạnh cả hai SVG. HTML tải bản dựng trình duyệt cố định phiên bản đó; trong dự án kiểm soát được, bạn có thể phục vụ cùng bản dựng cục bộ.

Lưu reader.html:

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Konva transparent image hit comparison</title>
<link rel="stylesheet" href="reader.css">
<main>
<h1>Transparent artwork: which node gets the click?</h1>
<p class="banner"><strong id="version">Loading Konva…</strong>. Original same-origin SVGs, actual Konva.Image nodes, and a separately clickable background. These are canvas hit pixels, not editable SVG path nodes. Desktop click test only; no mobile or accessibility audit.</p>
<div class="grid">
<section class="panel"><h2>1. Default rectangular hit</h2><div class="stage" id="default"></div><p>The hollow image still catches its transparent center and corner.</p><pre class="log" id="default-log"></pre></section>
<section class="panel"><h2>2. Cached alpha hit region</h2><div class="stage" id="alpha"></div><p>cache() then drawHitFromCache(0): the center and corner reach the background.</p><pre class="log" id="alpha-log"></pre></section>
<section class="panel"><h2>3. Opaque image fill</h2><div class="stage" id="fill"></div><p>A white fill behind this image is part of its cached scene. Its formerly empty pixels receive image hits.</p><pre class="log" id="fill-log"></pre></section>
<section class="panel"><h2>4. Replaced source, rebuilt cache</h2><div class="stage" id="updated"></div><p>The original hole is painted in filled.svg. Clear, replace, cache, and rebuild the hit region.</p><pre class="log" id="updated-log"></pre></section>
</div>
<p>Click these stage coordinates in each panel: solid (125,110), hole (195,130), transparent corner (305,55), and outside the image (20,20). The corner is inside the image viewport but outside its painted shape. Logs report actual click targets.</p>
 
</main>
<script src="https://unpkg.com/konva@10.9.0/konva.min.js"></script>
<script type="module" src="reader.js"></script>
</html>

Lưu reader.css:

body { margin: 32px; font: 16px/1.55 Arial, sans-serif; color: #183a42; background: #edf2ef; }
main { max-width: 1080px; margin: auto; }
h1 { font-size: 32px; margin-bottom: 12px; }
h2 { margin: 0 0 12px; font-size: 22px; }
p { margin: 10px 0; }
.banner { background: #dce8e4; padding: 18px; border-left: 5px solid #315d6f; }
.grid { display: grid; grid-template-columns: repeat(2, minmax(460px, 1fr)); gap: 20px; margin: 24px 0; }
.panel { background: white; padding: 20px; border: 1px solid #d1dbd5; border-radius: 12px; }
.stage { width: 420px; height: 260px; }
pre { white-space: pre-wrap; overflow-wrap: anywhere; background: #f8faf7; padding: 12px; }
table { border-collapse: collapse; width: 100%; margin-top: 20px; }
th, td { border-bottom: 1px solid #c9d5ce; padding: 10px; text-align: left; }
.log { min-height: 88px; margin-bottom: 0; font-size: 13px; }

Lưu reader.js:

const source = new Image();
source.src = './hollow.svg';
await source.decode();
const replacement = new Image();
replacement.src = './filled.svg';
await replacement.decode();
 
const clicks = [];
const scenes = [];
function makeScene(id, mode) {
  const stage = new Konva.Stage({ container: id, width: 420, height: 260 });
  const layer = new Konva.Layer();
  stage.add(layer);
  const background = new Konva.Rect({
    id: `${id}-background`, width: 420, height: 260, fill: '#eadfcd'
  });
  const artwork = new Konva.Image({
    id: `${id}-image`, image: source, x: 80, y: 40, width: 240, height: 180
  });
  if (mode === 'fill') artwork.fill('#ffffff');
  layer.add(background, artwork);
  if (mode !== 'default') {
    artwork.cache();
    artwork.drawHitFromCache(0);
  }
  layer.draw();
  const beforeUpdate = stage.getIntersection({ x: 195, y: 130 }).id();
  if (mode === 'update') {
    artwork.clearCache();
    artwork.image(replacement);
    artwork.cache();
    artwork.drawHitFromCache(0);
    layer.draw();
  }
  stage.on('click', (event) => {
    const point = stage.getPointerPosition();
    const record = {
      scene: id, x: point.x, y: point.y,
      target: event.target.id(), trusted: event.evt.isTrusted
    };
    clicks.push(record);
    document.getElementById(`${id}-log`).textContent +=
      `(${Math.round(point.x)}, ${Math.round(point.y)}) → ${record.target}\n`;
    document.dispatchEvent(new CustomEvent('fixture-click-recorded'));
  });
  const scene = { id, stage, artwork, beforeUpdate };
  scenes.push(scene);
  return scene;
}
makeScene('default', 'default');
makeScene('alpha', 'alpha');
makeScene('fill', 'fill');
makeScene('updated', 'update');
document.getElementById('version').textContent = `Konva ${Konva.version}`;

Phục vụ thư mục qua HTTP thay vì mở HTML như tệp cục bộ:

python -m http.server 8000

Mở http://localhost:8000/reader.html và chờ bốn sân khấu xuất hiện. SVG 240 × 180 đặt tại tọa độ sân khấu (80,40) trong mỗi sân khấu 420 × 260. Mỗi nền là một Konva.Rect riêng có lắng nghe sự kiện, nằm dưới ảnh. Bộ lắng nghe nhấp của sân khấu báo event.target.id(), xác định nút Konva được chọn thay vì chỉ phần tử DOM canvas.

await source.decode() chạy trước khi tạo bộ đệm. Lưu đệm sau khi nguồn thực sẵn sàng, không phải khi ảnh còn tải. Node API của Konva mô tả phương thức tạo và xóa bộ đệm.

3. Nhấp vùng đặc, lỗ, góc và nền

Thử bốn vị trí liệt kê dưới các bảng. Đây là tọa độ trong từng sân khấu, không phải đo từ cửa sổ trình duyệt.

Vị tríTọa độ sân khấuĐiều được thử
Hình đặc125,110Điểm đục nằm sâu trong biểu trưng
Lỗ gốc195,130Vùng trong suốt bên trong hollow.svg
Góc trong suốt305,55Trong hình chữ nhật ảnh nhưng ngoài hình bóng được tô
Ngoài ảnh20,20Nền nhận nhấp riêng

Bảng sau ghi loại đích đã thử. Nhật ký gồm tiền tố từng bảng, như alpha-background.

Cấu hìnhVùng đặcLỗ gốcGóc trong suốtNgoài ảnh
Ảnh mặc địnhẢnhẢnhẢnhNền
Vùng tương tác alpha đã lưu đệmẢnhNềnNềnNền
Ảnh lưu đệm có màu tô trắng đụcẢnhẢnhẢnhNền
Nguồn thay thế và bộ đệm dựng lạiẢnhẢnhNềnNền
So sánh Konva thực trong trình duyệt với vùng chữ nhật mặc định, vùng alpha lưu đệm, màu tô ảnh đục và nguồn thay thế, kèm ID đích nhấp đã ghi
Sân khấu Konva 10.9.0 thực với SVG tự tạo và đích nhấp máy tính đã ghi. Ảnh có lỗ dựa trên alpha cho nhấp tại lỗ và góc đến nền riêng. Màu tô ảnh đục và nguồn thay thế đã tô làm đổi kết quả.

Phép thử trình duyệt dùng nhấp con trỏ thật tại cả 16 vị trí và ghi trạng thái tin cậy sự kiện gốc, tọa độ sân khấu cùng ID đích. Nó cũng kiểm tra mã băm tệp nguồn, giải mã ảnh, kích thước sân khấu và ảnh, kết quả giao công khai và mẫu alpha gốc từ canvas kết xuất của từng nút ảnh.

Tại lỗ gốc, alpha của nút ảnh có lỗ bằng 0. Đối chứng tô đục và thay nguồn có alpha 255 tại đó. Nền trang riêng không làm chính ảnh có lỗ thành đục: nó thuộc nút Konva khác bên dưới. Đây là điểm mẫu bên trong, xa mép được khử răng cưa.

Đây là một phép thử trình duyệt máy tính với SVG tự tạo đơn giản và sân khấu không biến đổi. Nó không xác nhận hành vi di động/chạm, tương tác bàn phím, ma trận trình duyệt, cải thiện hiệu năng hoặc ngưỡng phù hợp mọi ảnh mép mềm. Lặp phép thử nhấp ở kích thước hiển thị và phép biến đổi thực tế của ứng dụng.

4. Dựng lại bộ đệm khi nguồn đổi

Bảng thứ tư bắt đầu với nguồn có lỗ và vùng tương tác alpha của nó. Sau đó xóa bộ đệm, đặt ảnh thay thế đã giải mã, lưu đệm lại và dựng lại vùng tương tác. Vị trí lỗ gốc đổi từ nền sang ảnh sau chuỗi đó.

Bộ đệm là ảnh chụp trạng thái đã kết xuất. Sau thay đổi ảnh hưởng pixel kết xuất, làm mới đồng thời cảnh lưu đệm và vùng tương tác dựa trên alpha. Đừng cho rằng gán ảnh khác đã cập nhật vùng tương tác trong bộ đệm hiện có. Với ảnh thay thế tải bất đồng bộ, chờ ảnh đó giải mã trước chuỗi trong ví dụ.

Bảng thứ ba cô lập nguyên nhân khác: artwork.fill('#ffffff') tô hình chữ nhật đục sau ảnh như một phần của chính nút ảnh. Dựng vùng tương tác từ cảnh lưu đệm đó sẽ gồm vùng đã tô. Bỏ màu tô không mong muốn của nút ảnh rồi dựng lại bộ đệm và vùng tương tác. Vùng trông trắng trong tệp nguồn cũng có thể là màu đục thực; kiểm tra độ trong suốt trước khi đổ lỗi nhận diện điểm nhấp.

Chẩn đoán lỗi đọc pixel và chọn đích riêng

Triệu chứngKiểm tra trước
Lỗ vẫn ghi đích là ảnhXác nhận lưu đệm sau giải mã, vùng tương tác được dựng lại và không có màu tô đục hoặc nền nguồn che lỗ
Hình đổi nhưng nhấp vẫn theo hình cũXóa và dựng lại bộ đệm cảnh cùng vùng tương tác alpha sau đổi nguồn
Lỗi đọc pixel hoặc canvas bị nhiễmKiểm tra nguồn ảnh và tiêu đề phản hồi trước khi diễn giải kết quả thử tương tác
Cả ảnh ngừng nhận sự kiệnKiểm tra listening, khả năng hiển thị, thứ tự lớp và nút khác có ở trên không
Lỗ đi đến sân khấu thay vì đối tượng dướiXác nhận đối tượng lắng nghe dự kiến thực sự tồn tại dưới điểm đó
Nhấp canvas hoạt động nhưng bàn phím khôngThiết kế điều khiển và ngữ nghĩa bàn phím riêng; pixel tương tác alpha không cung cấp chúng

Mẫu phục vụ cả hai SVG cùng nguồn với trang. Ảnh khác nguồn cần canvas sạch nguồn để đọc pixel. Hướng dẫn canvas bị nhiễm của Konva giải thích dùng crossOrigin cùng máy chủ cho phép yêu cầu CORS. Chỉ đặt crossOrigin = 'anonymous' không thể cấp quyền khi máy chủ không cho phép. Bài này không chạy trường hợp lỗi khác nguồn.

Đổi CSS pointer-events trên canvas ngoài không chọn pixel nào trong Konva.Image tương tác với nút bên trong. Tách chọn đích canvas khỏi chọn đích con trỏ DOM SVG. Cũng giữ bản gốc SVG: bản đồ tương tác lưu đệm là dữ liệu tương tác pixel, không thay tài liệu vector.

Tách khôi phục thiết kế khỏi nối sự kiện

Nếu ứng dụng chỉ cần đặt ảnh và nhận tương tác theo alpha, ảnh raster trong suốt phù hợp có thể đã đủ. Nếu chỉ còn PNG hoặc JPG và ứng dụng cũng cần hình học đường dẫn chỉnh được, quy trình chuyển ảnh thành vector của PerfectVector có thể giúp khôi phục SVG ứng viên. Kiểm tra hình bóng và lỗ, rồi chọn cách biểu diễn Konva và triển khai sự kiện. Ví dụ này dùng SVG tự tạo nguyên bản, không chuyển đổi PerfectVector.

Vector hóa không cài bộ lắng nghe, tạo điều khiển có khả năng tiếp cận, chọn đích nhấp hoặc giữ bộ đệm đồng bộ. Nếu đã có bản gốc SVG, sửa trực tiếp mã tương tác. Với tệp bất ngờ có ảnh chữ nhật đầy đủ bên trong, dùng kiểm tra raster nhúng trong SVG trước khi cho rằng nội dung là các đường riêng chỉnh được.

Câu hỏi thường gặp

Tại sao pixel trong suốt trong ảnh Konva nhận nhấp? Nút Image mặc định có thể dùng vùng chữ nhật để nhận tương tác. Sau khi nguồn sẵn sàng, lưu đệm và dùng drawHitFromCache với ngưỡng alpha số phù hợp, rồi vẽ lại và thử đích thực tế.

drawHitFromCache nhận đối số gì? API hiện tại nhận ngưỡng alpha số nguyên tùy chọn từ 0 đến 255, mặc định 0. Ví dụ đã thử truyền 0. Nó không truyền hàm gọi lại hoặc dùng bộ lọc Threshold trực quan.

Vì sao màu tô trắng khiến lỗ SVG lại nhận nhấp? Màu tô đục trên nút Image thành phần của cảnh lưu đệm. Alpha đã lưu khi đó gồm vùng tô đó. Bỏ màu tô không mong muốn và dựng lại bộ đệm cảnh cùng vùng tương tác.

Vùng tương tác alpha có làm đường SVG chỉnh độc lập được không? Không. Thiết kế vẫn là một nút Image. Dùng các nút Path riêng phù hợp và mô hình cảnh rõ ràng khi ứng dụng cần điều khiển từng vùng vector.

Nguồn

  1. Konva: Image Events — Hành vi tương tác ảnh mặc định và tạo vùng tương tác từ thiết kế lưu đệm.
  2. Konva: Shape API — Tham số alphaThreshold số hiện hành và phạm vi.
  3. Konva: Node API — Tạo, xóa bộ đệm, đích sự kiện và phương thức nút công khai.
  4. Konva: Hướng dẫn canvas bị nhiễm — Hạn chế nguồn, CORS và lỗi đọc pixel.
  5. Konva: SVG trên canvas — Kết xuất toàn ảnh so với đường vector được dựng riêng.

Khi thiếu hình học chỉnh được, chuẩn bị SVG ứng viên bằng PerfectVector, kiểm tra lỗ, rồi thử riêng đích nhấp Konva và cập nhật bộ đệm mong muốn.

Thêm từ blog

PerfectVector

Bắt đầu với SVG gọn sạch hơn
và dễ chỉnh sửa hơn

Không cần thẻ tín dụng