ShukantPal / pixi-essentials

The best goodies for performant, enterprise-level applications built on PixiJS
https://api.pixijs.io
MIT License
285 stars 37 forks source link

Unable to interact with svgScene object after adding it to the scene #42

Open mikecjtio opened 3 years ago

mikecjtio commented 3 years ago

I've tried multiple ways (such as attaching events, defining hitArea, trying hitTest and so...) to add interactivity to SVGScene output after loading it using @pixi-essentials/svg library but the events are never triggered.

How do we add interaction to the svg after loading it?

import { SVGScene } from '@pixi-essentials/svg';

//load svg from url
const svgMarkup = await fetch("<svg_url>").then((data) => data.json());
const svgDOM = new DOMParser().parseFromString(svgMarkup, "image/svg+xml");
const svgEl = svgDOM.documentElement;

//add svg to our scene - added event gets called 
let svg = new SVGScene(svgEl);
svg.on('added', function(){ 
  console.log('svg added'); 
});

//svg interactions - NOTE: Click/Mouse events are not triggered
svg.interactive = true;
svg.buttonMode = true;
svg.on('click', function(){
  console.log('svg clicked');
});
svg.on('mouseenter', function(){
  console.log('svg mouseentered');
});
ShukantPal commented 3 years ago

The SVGScene is optimized for rendering speed. It doesn't have a _contains method by default for hit testing.

However, setting a hitArea should definitely work. Can you create a minimal reproduction of this with hitArea?

mikecjtio commented 3 years ago

Thanks for the quick reply.

I tried again with hitArea and the code below worked!

//svg interactions
svg.interactive = true;
svg.buttonMode = true;
svg.hitArea = new PIXI.Rectangle(0, 0, canvas_width, canvas_height)
svg.on('pointerdown', function(){
  console.log('Clicked inside hitArea');
});

I wanted to use the entire SVG as the hitArea (i.e. making only the visible pixels interactive and ignoring transparent area). Is this possible using this library? I wanted to use hitTest on the SVG for this rather than defining a rectangle. demo

Alternatively, I've found hitarea-shapes (Demo) which requires us to manually create those shapes. https://github.com/explooosion/hitarea-shapes

ShukantPal commented 3 years ago

I think you can extend SVGScene and implement containsPoint.

public containsPoint({ x, y }): void {
  return this.root.containsPoint(x, y)
}