Abaikan Area SVG Transparan dalam Deteksi Klik Konva
Buat area SVG transparan mengabaikan klik di Konva. Coba deteksi hit berbasis cache, uji lubang dan latar, serta bangun ulang hit setelah sumber berubah.
Di halaman ini
- Pisahkan gambar dari area hit-nya
- 1. Simpan dua masukan SVG lengkap
- 2. Muat, cache, dan catat target sebenarnya
- 3. Klik area solid, lubang, sudut, dan latar
- 4. Buat ulang cache saat sumber berubah
- Diagnosis kegagalan pembacaan piksel dan penargetan secara terpisah
- Pisahkan pemulihan desain dari pemasangan peristiwa
- Tanya jawab
- Sumber
Agar area transparan Konva.Image mengabaikan klik, tunggu gambar sumber selesai didekode, panggil imageNode.cache(), lalu panggil imageNode.drawHitFromCache(0) dan gambar ulang layer. Alpha adegan dalam cache, yaitu opasitas piksel, kemudian menentukan piksel gambar yang berpartisipasi dalam deteksi hit.
Node gambar normal dapat menerima peristiwa di seluruh persegi panjangnya, termasuk lubang SVG kosong. Tutorial Image Events Konva menunjukkan alternatif berbasis alpha. Artikel ini menguji SVG orisinal berlubang di atas latar yang dapat diklik secara terpisah, sehingga lubang yang berhenti menangkap klik gambar memiliki target nyata di bawahnya untuk menerima klik.
Ini mengubah area interaksi canvas. Cara ini tidak membuat node Konva.Path yang dapat diedit dari SVG atau mengubah aturan DOM SVG pointer-events.
Pisahkan gambar dari area hit-nya
Area hit adalah area yang dipakai Konva untuk memilih target peristiwa. Bentuknya dapat berbeda dari desain terlihat. Untuk beberapa aplikasi, target persegi panjang luas memang disengaja; untuk lainnya, lubang transparan seharusnya memungkinkan pengguna memilih objek di bawahnya.
| Interaksi yang diinginkan | Titik awal |
|---|---|
| Memilih seluruh gambar dari mana saja dalam persegi panjangnya | Perilaku hit Image default |
| Membiarkan piksel gambar transparan menjangkau node di bawahnya | Cache gambar dan buat area hit dari alpha |
| Mengedit atau menambahkan tindakan mandiri pada area vektor individual | Pilih path Konva terpisah dan tentukan perilakunya |
| Mengendalikan target pointer di dalam DOM SVG inline | Gunakan panduan pointer-events SVG terpisah |
Shape API saat ini menerima bilangan bulat alphaThreshold dari 0 hingga 255; default-nya 0. Berikan angka di sini, bukan callback. Ini berbeda dari filter visual Threshold. Contoh memakai 0 dengan interior sepenuhnya opak dan lubang sepenuhnya transparan; contoh ini tidak menetapkan ambang pilihan untuk bayangan lembut atau tepi antialias.
1. Simpan dua masukan SVG lengkap
Buat folder kosong. Simpan lambang orisinal berlubang ini sebagai 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>Subpath dalam membuat lubang menurut aturan fill even-odd. Simpan bentuk luar yang sama tanpa subpath dalam tersebut sebagai 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>Berkas kedua adalah kontrol perubahan sumber. Berkas ini mengisi lokasi yang sebelumnya kosong. Tidak satu pun berkas berisi persegi panjang latar putih atau bitmap tertanam.
2. Muat, cache, dan catat target sebenarnya
Contoh ini memakai Konva 10.9.0. Simpan tiga berkas ini di sebelah kedua SVG. HTML memuat build browser dengan versi tetap tersebut; untuk proyek terkontrol, Anda dapat menyajikan build yang sama secara lokal.
Simpan 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>Simpan 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; }Simpan 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}`;Sajikan folder ini melalui HTTP, bukan membuka HTML sebagai berkas lokal:
python -m http.server 8000Buka http://localhost:8000/reader.html dan tunggu keempat stage muncul. SVG 240 × 180 ditempatkan pada koordinat stage (80,40) dalam setiap stage 420 × 260. Setiap latar adalah Konva.Rect tersendiri yang mendengarkan peristiwa, di bawah gambar. Listener klik stage melaporkan event.target.id(), yang mengidentifikasi node Konva terpilih, bukan sekadar elemen DOM canvas.
await source.decode() berjalan sebelum pembuatan cache. Buat cache setelah sumber sebenarnya siap, bukan saat gambar masih dimuat. Node API Konva mendokumentasikan metode cache dan clear-cache.
3. Klik area solid, lubang, sudut, dan latar
Uji empat lokasi yang tercantum di bawah panel. Ini koordinat dalam setiap stage, bukan koordinat yang diukur dari jendela browser.
| Lokasi | Koordinat stage | Yang diuji |
|---|---|---|
| Desain solid | 125,110 | Titik opak jauh di dalam lambang |
| Lubang asli | 195,130 | Interior transparan dalam hollow.svg |
| Sudut transparan | 305,55 | Di dalam persegi panjang gambar, di luar siluet berwarnanya |
| Di luar gambar | 20,20 | Latar yang dapat diklik secara terpisah |
Tabel berikut mencatat jenis target yang diuji. Log menyertakan awalan setiap panel, seperti alpha-background.
| Konfigurasi | Solid | Lubang asli | Sudut transparan | Di luar gambar |
|---|---|---|---|---|
| Gambar default | Gambar | Gambar | Gambar | Latar |
| Area hit alpha dalam cache | Gambar | Latar | Latar | Latar |
| Gambar dalam cache dengan fill putih opak | Gambar | Gambar | Gambar | Latar |
| Sumber diganti dan cache dibuat ulang | Gambar | Gambar | Latar | Latar |

Pengujian browser memakai klik pointer nyata pada seluruh 16 lokasi dan mencatat status trusted peristiwa asli, koordinat stage, serta ID target. Pengujian juga memeriksa hash berkas sumber, dekode gambar, dimensi stage dan gambar, hasil irisan publik, serta sampel alpha asli dari canvas hasil render setiap node gambar.
Pada lubang asli, alpha node gambar berlubang adalah 0. Kontrol fill opak dan sumber pengganti memiliki alpha 255 di sana. Latar halaman terpisah tidak membuat gambar berlubang itu sendiri opak: latar tersebut milik node Konva lain di bawahnya. Ini sampel interior, jauh dari batas antialias.
Ini satu pengujian browser desktop dengan SVG orisinal sederhana dan stage tanpa transformasi. Pengujian tidak membuktikan perilaku seluler/sentuh, interaksi keyboard, matriks lintas browser, peningkatan performa, atau ambang yang cocok untuk setiap gambar bertepi lembut. Ulangi uji klik pada ukuran tampilan dan transformasi sebenarnya dalam aplikasi Anda.
4. Buat ulang cache saat sumber berubah
Panel keempat dimulai dengan sumber berlubang dan area hit alpha-nya. Lalu panel membersihkan cache, memasang gambar pengganti yang sudah didekode, membuat cache lagi, dan membangun ulang area hit. Lokasi lubang asli berubah dari latar menjadi gambar setelah urutan tersebut.
Cache adalah snapshot hasil render. Setelah perubahan yang memengaruhi piksel hasil render, perbarui adegan dalam cache dan area hit berbasis alpha-nya bersama-sama. Jangan menganggap penetapan gambar berbeda telah memperbarui area hit dalam cache yang sudah ada. Untuk pengganti yang dimuat asinkron, tunggu pengganti itu didekode sebelum urutan pada contoh.
Panel ketiga mengisolasi penyebab berbeda: artwork.fill('#ffffff') melukis persegi panjang opak di belakang gambar sebagai bagian node gambar yang sama. Membuat area hit dari adegan dalam cache itu menyertakan area berwarna tersebut. Hapus fill node gambar yang tidak diinginkan, lalu buat ulang cache serta area hit. Area yang tampak putih dalam sumber juga bisa berupa warna opak sebenarnya; periksa transparansi sebelum menyalahkan deteksi hit.
Diagnosis kegagalan pembacaan piksel dan penargetan secara terpisah
| Gejala | Periksa dahulu |
|---|---|
| Lubang masih mencatat gambar | Pastikan cache dibuat setelah dekode, area hit dibuat ulang, dan tidak ada fill opak atau latar sumber menutupi lubang |
| Desain berubah tetapi klik masih mengikuti bentuk lama | Bersihkan dan buat ulang cache adegan serta area hit alpha setelah sumber berubah |
| Muncul kesalahan pembacaan piksel atau tainted canvas | Periksa origin gambar dan header respons sebelum menafsirkan hasil uji hit apa pun |
| Seluruh gambar berhenti menerima peristiwa | Periksa listening, visibilitas, urutan layer, dan apakah node lain berada di atasnya |
| Lubang mencapai stage alih-alih objek bawah | Pastikan objek pendengar yang dimaksud benar-benar ada di bawah titik itu |
| Klik canvas bekerja tetapi keyboard tidak | Rancang kontrol serta semantik keyboard secara terpisah; piksel hit alpha tidak menyediakannya |
Fixture ini menyajikan kedua SVG dari origin yang sama dengan halaman. Gambar lintas origin memerlukan canvas origin-clean untuk pembacaan piksel. Panduan tainted canvas Konva menjelaskan penggunaan crossOrigin bersama server yang mengizinkan permintaan CORS. Menetapkan crossOrigin = 'anonymous' saja tidak memberi akses jika server tidak mengizinkannya. Artikel ini tidak menjalankan kasus kegagalan lintas origin.
Mengubah CSS pointer-events pada canvas luar tidak memilih piksel di dalam Konva.Image yang mengenai node internalnya. Pisahkan penargetan canvas dari penargetan pointer DOM SVG. Simpan juga master SVG: peta hit dalam cache adalah data interaksi berbasis piksel, bukan pengganti dokumen vektor.
Pisahkan pemulihan desain dari pemasangan peristiwa
Jika aplikasi hanya membutuhkan penempatan gambar dan hit berbasis alpha, raster transparan yang sesuai mungkin sudah cukup. Jika hanya PNG atau JPG yang tersisa dan aplikasi juga memerlukan geometri path yang dapat diedit, alur gambar-ke-vektor PerfectVector dapat membantu memulihkan kandidat SVG. Periksa siluet serta lubang, lalu pilih representasi Konva dan implementasikan peristiwanya. Contoh ini memakai SVG asli orisinal dan tidak melakukan konversi PerfectVector.
Vektorisasi tidak memasang listener, membuat kontrol aksesibel, memilih target klik, atau menyinkronkan cache. Jika master SVG sudah ada, perbaiki kode interaksi secara langsung. Untuk berkas yang tiba-tiba memiliki gambar persegi panjang penuh di dalamnya, gunakan pemeriksaan raster tertanam SVG sebelum menganggap isinya path terpisah yang dapat diedit.
Tanya jawab
Mengapa piksel transparan dalam gambar Konva saya menerima klik? Node Image default dapat memakai area persegi panjangnya untuk hit. Setelah sumber siap, buat cache dan gunakan drawHitFromCache dengan ambang alpha numerik yang sesuai, lalu gambar ulang serta uji target sebenarnya.
Argumen apa yang diterima drawHitFromCache? API saat ini menerima ambang alpha bilangan bulat opsional dari 0 hingga 255, dengan default 0. Contoh yang diuji memberi 0. Contoh tidak memberi callback atau memakai filter visual Threshold.
Mengapa fill putih membuat lubang SVG dapat diklik lagi? Fill opak pada node Image menjadi bagian adegan dalam cache. Alpha cache kemudian menyertakan area berwarna itu. Hapus fill yang tidak diinginkan dan buat ulang cache adegan serta area hit.
Apakah area hit alpha membuat path SVG dapat diedit sendiri-sendiri? Tidak. Desain tetap menjadi satu node Image. Gunakan node Path terpisah yang sesuai dan model adegan eksplisit jika aplikasi memerlukan kontrol area vektor individual.
Sumber
- Konva: Image Events — Perilaku hit gambar default dan pembuatan area hit dari desain dalam cache.
- Konva: Shape API — Parameter alphaThreshold numerik saat ini dan rentangnya.
- Konva: Node API — Pembuatan dan pembersihan cache, target peristiwa, serta metode node publik.
- Konva: Panduan tainted canvas — Batasan origin, CORS, dan kegagalan pembacaan piksel.
- Konva: SVG pada canvas — Render seluruh gambar versus path vektor yang dibuat secara terpisah.
Saat geometri yang dapat diedit belum ada, siapkan kandidat SVG dengan PerfectVector, periksa lubangnya, lalu uji target klik Konva yang dimaksud serta pembaruan cache secara terpisah.
Lebih banyak dari blog

Penanda SVG di Matplotlib: Periksa Jalurnya
Gunakan jalur SVG sederhana sebagai penanda diagram pencar Matplotlib. Ulangi pemeriksaan pusat, orientasi, lubang, dan ukuran pada ekspor SVG serta PDF asli.

Tambahkan Watermark SVG ke PDF yang Ada dengan Python
Gabungkan watermark SVG ke PDF dengan svglib, ReportLab, dan pypdf. Periksa opasitas, halaman terpotong, rotasi, teks yang dipertahankan, serta urutan lapisan.
