Как нарисовать кликабельную линию в PIXI.js, используя PIXI.Graphics?

Я получил следующий код:

const linksGraphics = new PIXI.Graphics();

const update = () => {
linksGraphics.clear();
linksGraphics.alpha = 1;
if (forceLinkActive) { 
  data.links.forEach(link => {
    let { source, target } = link;
    linksGraphics.lineStyle(2, 0x000000);
    linksGraphics.moveTo(source.x, source.y);
    linksGraphics.lineTo(target.x, target.y);
  });
  linksGraphics.endFill();
}  }


app.ticker.add( () => update() );

Где data.links - это массив граничных данных {источник: номер, цель: номер}. Если я правильно понимаю, все строки являются частью объекта PIXI.Graphics. Но что мне нужно

  1. каждая строка должна иметь свою непрозрачность
  2. каждая строка должна иметь событие для наведения мыши

Есть идеи, как изменить мой код?

Благодарю.

3 ответа

Вы можете определить hitArea на графике. А с помощью getBounds() вы можете сделать строку доступной для кликов. После того, как вы это сделаете, вы также можете присвоить графике pointerEvents.

      const linksGraphics = new PIXI.Graphics();

const update = () => {
  linksGraphics.clear();
  linksGraphics.alpha = 1;

  if (forceLinkActive) { 
    data.links.forEach(link => {
       let { source, target } = link;
       linksGraphics.lineStyle(2, 0x000000);
       linksGraphics.moveTo(source.x, source.y);
       linksGraphics.lineTo(target.x, target.y);

       //A line itself is not clickable
       linksGraphics.hitArea = linksGraphics.getBounds();
    });
    linksGraphics.endFill();
  }  
}


app.ticker.add( () => update() );

Прошло некоторое время, но могу сделать предложение. Линии не реагируют на мышь/указатель на события в pixijs.

Вместо этого вы можете захотеть сопровождать преобразованный прямоугольник альфа-значением 0 и слушать мышь/указатель с этим прямоугольником.

Например, давайте изменим альфа-значение линии, когда мышь/указатель наводит соответствующий прямоугольник.

      const app = new PIXI.Application({
    width: window.innerWidth,
    height: window.innerHeight,
    backgroundColor: 0x283230
});
document.body.appendChild(app.view);

// 1. PRELIMINARY COMPUTATIONS
// Coordinates of the end points of a line
let x0 = 100;
let y0 = 100;
let x1 = 200;
let y1 = 200;
// Find midpoint for translation
let xmid = 0.5*(x0+x1);
let ymid = 0.5*(y0+y1);
// Length of the line
let length = Math.hypot(x0-x1, y0-y1);
// Alignment angle of the line, i.e. angle with the x axis
let angle = Math.atan((y1-y0)/(x1-x0));

// 2. LINE 
line = new PIXI.Graphics();
// Arbitrary line style, say we have a non-white background
line.lineStyle(8,0xffffff,1);
line.moveTo(x0,y0);
line.lineTo(x1,y1);


// 3. ACCOMPANYING RECTANGLE
line.rectangle = new PIXI.Graphics();
line.rectangle.beginFill(0xffffff);
// Since we are going to translate, think of 0,0 is the center point on the rectangle
// Width of the rectangle is selected arbitrarily as 30
const width = 30;
line.rectangle.drawRect(-length/2,-width/2,length,width);
line.rectangle.endFill();
line.rectangle.alpha = 0;
line.rectangle.interactive = true;
line.rectangle.on("pointerover", reactOver);
line.rectangle.on("pointerout", reactOut);
// Apply transformation
line.rectangle.setTransform(xmid, ymid,1,1,angle);

app.stage.addChild(line);
// Add rectangle to the stage too.
app.stage.addChild(line.rectangle);

// Let's change alpha value of the line when user hovers.
function reactOver(){
   line.alpha = 0.5;
}
function reactOut(){
   line.alpha = 1;
}

К PEN, наведите курсор на строку в pixijs

Мы можем расширить эту логику, например, до прямоугольника. Но на этот раз вам нужны два сопутствующих прямоугольника (с альфа=0), один из которых шире, а другой уже, чем незаполненный прямоугольник. Например,

      const app = new PIXI.Application({
    width: window.innerWidth,
    height: window.innerHeight,
    backgroundColor: 0x283230
});
document.body.appendChild(app.view);
const x = 100;
const y = 100;
const width = 150;
const height = 100;
const hoverWidth = 20;

const rect = new PIXI.Graphics();
rect.lineStyle(4, 0xffffff,1);
rect.drawRect(x,y,width,height);
rect.outer = new PIXI.Graphics();
rect.inner = new PIXI.Graphics();
// Fill outer
rect.outer.alpha = 0;
rect.outer.beginFill(0xffffff);
rect.outer.drawRect(x-hoverWidth/2, y-hoverWidth/2, width+hoverWidth, height+hoverWidth);
rect.outer.endFill();
// Fill inner
rect.inner.alpha = 0;
rect.inner.beginFill(0xffffff);
rect.inner.drawRect(x+hoverWidth/2, y+hoverWidth/2, width-hoverWidth, height-hoverWidth);
rect.inner.endFill();
// Add interaction and listeners
rect.outer.interactive = true;
rect.inner.interactive = true;
rect.outer.on("pointerover", pOverOuter);
rect.outer.on("pointerout", pOutOuter);
rect.inner.interaction = true;
rect.inner.on("pointerover", pOverInner);
rect.inner.on("pointerout", pOutInner);
app.stage.addChild(rect);
app.stage.addChild(rect.outer);
app.stage.addChild(rect.inner);


// Listeners
let overOuter = false;
let overInner = false;
function pOverOuter(){
  overOuter = true;
  changeAlpha();
  // rect.alpha = 0.5;
}

function pOutOuter(){
  overOuter = false;
  changeAlpha();
}

function pOverInner(){
  overInner = true;
  changeAlpha();
  // rect.alpha = 1;
}

function pOutInner(){
  overInner = false;
  changeAlpha();
  // rect.alpha = 0.5;
}

function changeAlpha(){
  rect.alpha = (overOuter && !overInner)? 0.5: 1;
}

Для PEN наведите курсор на прямоугольник в pixijs

Для первого требования попробуйте создать отдельные графические объекты для рисования каждой линии и установить альфа для каждой линии. Для вашего второго требования, вам нужно установить интерактивное свойство объекта graphics (linksGraphics) в true, как показано ниже,

linksGraphics.interactive = true;

и затем присоедините функцию, которая будет выполняться при наведении мыши, как показано ниже,

var mouseOverAction = function () {
       //Some code
};
linksGraphics.on('mouseover', mouseOverAction);
Другие вопросы по тегам