Reputation: 23
I know that it's pretty easy to trigger an action in JointJS if you click a markup selector. We can simply add a custom event attr of that markup element, but as far as I know only pointer events are allowed. Is there any way to archive the same for hovering?
For example I have a custom cell with 4 buttons, that are just a bunch of svg tag added via the markup. I want to change the opacity of all other elements on the canvas, depending on the button that was hovered. I have an idea on how to filter everything and change the opacity, but I have no idea on how to trigger that event and know what selector I'm hovering.
Upvotes: 0
Views: 402
Reputation: 336
You could take advantage of the 'element:mouseenter'
event on the paper, then event.target
can give you access to sub-elements on the shape.
In the following example, when you hover a color on the button shape, the standard.Rectangle
type shapes all change to that color.
This solution takes advantage of adding classes via markup
, and checking if the target has the particular class.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.6.5/joint.css" />
<style>
.joint-paper {
display: inline-block;
border: 1px solid gray;
}
</style>
</head>
<body>
<!-- content -->
<div id="myholder"></div>
<!-- dependencies -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.4.1/backbone.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.6.5/joint.js"></script>
<!-- code -->
<script type="text/javascript">
var namespace = joint.shapes;
var graph = new joint.dia.Graph({}, { cellNamespace: namespace });
var paper = new joint.dia.Paper({
el: document.getElementById('myholder'),
model: graph,
width: 600,
height: 300,
gridSize: 1,
cellViewNamespace: namespace
});
class ButtonShape extends joint.dia.Element {
defaults() {
return {
...super.defaults,
type: 'MyShape',
size: {
width: 120,
height: 155
},
attrs: {
body: {
width: 'calc(w)',
height: 'calc(h)',
fill: '#ffffff',
stroke: '#333333',
strokeWidth: 2,
rx: 5,
ry: 5,
pointerEvents: 'none'
},
rectUpper: {
width: 'calc(0.8*w)',
height: 'calc(h/2.5)',
fill: 'cornflowerblue',
stroke: '#333333',
strokeWidth: 2,
x: 'calc(0.1*w)',
y: 10
},
rectLower: {
width: 'calc(0.8*w)',
height: 'calc(h/2.5)',
fill: 'tomato',
stroke: '#333333',
strokeWidth: 2,
x: 'calc(0.1*w)',
y: 'calc(h - calc(h/2.5 + 10))'
},
}
};
}
preinitialize() {
this.markup = [{
tagName: 'rect',
selector: 'body'
}, {
tagName: 'rect',
selector: 'rectUpper',
className: 'upper'
}, {
tagName: 'rect',
selector: 'rectLower',
className: 'lower'
}];
}
}
const buttonShape = new ButtonShape();
buttonShape.position(10, 10);
buttonShape.addTo(graph);
for(let i = 0; i < 5; i++) {
const rect = new joint.shapes.standard.Rectangle();
rect.position(i * 60 + 10, 200);
rect.resize(50, 50);
rect.addTo(graph);
}
paper.on('element:mouseenter', function (cellView, evt) {
const rectangles = graph.getElements().filter((el) => el.get('type') === 'standard.Rectangle');
if (evt.target.classList.contains('upper')) {
rectangles.forEach((rect) => {
rect.attr('body/fill', 'cornflowerblue')
});
}
if (evt.target.classList.contains('lower')) {
rectangles.forEach((rect) => {
rect.attr('body/fill', 'tomato')
});
}
});
</script>
</body>
</html>
Upvotes: 0