I have created a simple code to mess around and learn with SVG files and eventlisteners.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG Mouse Pointer Change</title>
<style>
#svg5 {
width: 50%; /* Adjust the width as needed */
height: auto; /* Maintain aspect ratio */
}
</style>
<script>
window.onload = function() {
var svgObject = document.getElementById('svg5');
svgObject.addEventListener('load', function() {
var svgDocument = svgObject.contentDocument;
var rect = svgDocument.getElementById('rect237');
// Function to change mouse pointer to crosshair
function changeCursorToCrosshair() {
console.log("Mouse entered rect237");
document.body.style.cursor = 'crosshair';
}
// Function to change mouse pointer to default
function changeCursorToDefault() {
console.log("Mouse left rect237");
document.body.style.cursor = 'default';
}
// Add event listener for mouse enter
rect.addEventListener('mouseenter', function() {
console.log("Mouse entered rect237");
changeCursorToCrosshair();
});
// Add event listener for mouse leave
rect.addEventListener('mouseleave', function() {
console.log("Mouse left rect237");
changeCursorToDefault();
});
});
};
</script>
</head>
<body>
<object id="svg5" type="image/svg+xml" data="./img/simple_pitch.svg"></object>
</body>
</html>
However when testing the code nothing occurs. I have added some console logs but nothing is shown. I hope someone can let me know what I’m missing.
Thanks
2
Answers
Two things: Since the
<object>
‘s data is set inline in the markup, thewindow.load
event will wait for the<object>
‘s load event before it fires. So when you are in thewindow.load
event handler, the<object>
‘s one has already fired and won’t again until itsdata
attribute changes.This means that the
svgObject
‘s load event won’t fire and your callback won’t be called.So remove the line
svgObject.addEventListener('load', ...
and call directly your code in thewindow.onload
event handler.Then,
document.body.style.cursor = 'crosshair';
will set thecursor
of the outer HTML document’s<body>
tag, but the element you are hovering is the inner SVG document’s<rect>
element. Both documents are isolated and the<object>
‘s inner document will capture the pointer events, including the setting of the cursor.If you want to change the cursor, you can set it to
svgDocument.documentElement.style.cursor = ...
.(Obviously you could also have achieved the same with a simple
rect { cursor: crosshair }
CSS rule, but I get it’s just a test to use events.)It is not clear from the question if you are running the HTML and SVG document from a web server. To make this work (to get the load event to fire on the object element) you need to run a web server. The load event will not fire and you cannot get access to the
contentDocument
if you just open the HTML file from the file system.And in regards to the comments about the order of events. You must wait till the DOM is loaded (either setting the
window.onload
or using theaddEventListener()
method) before you can add an event listener to the object element — just like you already did.Here is an example, where I changed the way that the crosshair style is set. The style of the cursor is not "tied to" the events of the mouse entering and leaving an element. If an element has a cursor style, then the cursor will change when the element is hovered. And then you can have the enter and leave events do something else (like, typically change the DOM).