I'm creating a draggable riot js based SVG element.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g name="green" data-is="r-rect" x="30" y="230" width="256" height="64" rx="5" ry="5" draggable="true" fill="green"></g>
<g name="blue" data-is="r-rect" x="10" y="110" width="256" height="64" rx="5" ry="5" draggable="true" fill="blue"></g>
</svg>
r-rect.tag
<r-rect>
<rect ref="rect" onmousedown={hold} />
<script>
tag = this;
tag.hold = hold;
tag.x= Number.parseInt(opts.x);
tag.y= Number.parseInt(opts.y);
tag._name= opts.name;
tag.on("mount", function(e) {
tag.refs.rect.setAttribute("x", opts.x);
tag.refs.rect.setAttribute("y", opts.y);
tag.refs.rect.setAttribute("width", opts.width);
tag.refs.rect.setAttribute("height", opts.height);
opts.rx && (tag.refs.rect.setAttribute("rx", opts.rx) );
opts.ry && (tag.refs.rect.setAttribute("ry", opts.ry) );
})
function hold(e){
console.log(tag._name)
}
</script>
</r-rect>
I add 2 r-rect tags. Try to drag blue rectangle. But mousedown event of green rectangle triggers always .
http://jsfiddle.net/1k2gacy1/1/
I found the issue. It was happening because I was assigning the tag instance in global variable. So I've changed this line tag = this; to var tag = this;. And it solved the issue.
Related
Why a light colored rectangle background showed up on the area behind xlink every time it is touched or clicked?
Here is my SVG code:
<svg version="1.1" viewBox="0 0 147.86 258.44" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g class="bglyr" fill="none" transform="translate(-30.575,-20.926)">
<a xlink:href="https://google.com">
<path id="link1" fill="none" onmouseover="change(this)" onmouseout="unchange(this)" d="m104.43 242.44 11.742 6.1664 57.094 29.884-137.62 0.0617z" />
<a />
</g>
</svg>
JavaScript:
function change(item) {
item.style.fill = "#42d46b";
item.style.opacity = "1.0";
}
function unchange(item) {
item.style.fill = "none";
item.style.opacity = "0.0";
}
Just in case your question is actually about why your example code doesn't work, then I can explain that for you.
Mouse events won't be triggered if your <path> has nothing to hover over. When the fill is "none" or the opacity is 0. No mouse events will be triggered. To fix this, use fill="transparent" instead. This behaves the same way, but is detected as if it was any other non-transparent fill colour.
function change(item) {
item.style.fill = "#42d46b";
}
function unchange(item) {
item.style.fill = "transparent";
}
<svg version="1.1" viewBox="0 0 147.86 258.44" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g class="bglyr" fill="none" transform="translate(-30.575,-20.926)">
<a xlink:href="https://google.com">
<path id="link1" fill="transparent" onmouseover="change(this)" onmouseout="unchange(this)" d="m104.43 242.44 11.742 6.1664 57.094 29.884-137.62 0.0617z" />
</a>
</g>
</svg>
I am trying to modify the height of a rectangle in svg. First of all my svg is correctly displayed before i use the Animated api. Then i try to bind a height variable to the SVG as So :
render() {
let AnimatedRectangle = Animated.createAnimatedComponent(Rect);
let {height} = this.state
return (
<View style={styles.wrapper}>
<Svg height="100" width="100" x="0" y="0" fill="#333">
<AnimatedRectangle
x="0"
y="0"
width="4"
height={height}
fill="#333"
/>
<Rect x="10" y="0" width="4" height="7" fill="#333" />
<Rect x="20" y="0" width="4" height="7" fill="#333" />
</Svg>
</View>
);}
Here is my state and componentDidMount method :
state = {
height: new Animated.Value(5)
};
componentDidMount() {
Animated.timing(
// Animate value over time
this.state.height, // The value to drive
{
toValue: 30 // Animate to final value of 1
}
).start(); // Start the animation
}
This is not working even though my Animation is working. Indeed, if i bind the height to a simple Animated.View, the height is correctly modified.
Here is the error i am getting :
It's possible to set the property of the elements of SVG direcly from the script?
For example
<svg width="100px" height="100px" version="1.1" onload="setValues()" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">
// <![CDATA[
function setValues() {
//Set cx || cy || whatever of circle
// Set property of rect
}
// ]]>
</script>
<circle id="circleId" cx="50" cy="50" r="45" fill="green" />
<rect id="rectId" height="40" width="400" y="0" x="170" style="fill:#ffffff" />
</svg>
Sure, setAttribute will do that.
<svg width="100px" height="100px" version="1.1" onload="setValues()" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">
// <![CDATA[
function setValues() {
// Set property of circle
document.getElementById("circleId").setAttribute('cx', '20');
// Set property of rect
document.getElementById("rectId").setAttribute('x', '10');
document.getElementById("rectId").setAttribute('style', 'fill:red');
}
// ]]>
</script>
<circle id="circleId" cx="50" cy="50" r="45" fill="green" />
<rect id="rectId" height="40" width="400" y="0" x="170" style="fill:#ffffff" />
</svg>
<div style="float: left; padding: 10px; border: 1px solid;
background: #ccc">random text</div>
Is there a way to achieve something like this in SVG? I mean to have a rectangle and a text and:
a) rectangle's width and height are dynamic, so when I change the text, the rectangle adjust its size
b) when I move the rectangle, the text goes with it
And would it be easier to achieve something like this in <canvas>?
EDIT:
<defs>
<text id="text1" x="90" y="100" style="text-anchor:start;font-size:30px;">
THIS IS MY HEADER</text>
</defs>
<filter x="0" y="0" width="1" height="1" id="background">
<feFlood flood-color="gray"/>
<feComposite in="SourceGraphic"/>
</filter>
<use xlink:href="#text1" fill="black" filter="url(#background)"/>
Erik Dahlström proposed something like this. How to put padding to the background, how to add eg. shadow or border to the rectangle? And, this doesn't work in IE9, so I cannot accept it. I could just use <foreignObject> if there was a support for it in IE.
And I just figured out the answer for b) point of my question. You have to put both elements in the group:
<g>
<rect x="0" y="0" width="100" height="100" fill="red"></rect>
<text x="50" y="50" font-size="14" fill="blue" text-anchor="middle">Hello</text>
</g>
And then you can move the group using transform param:
<g transform="translate(x, y)">
Seems to work correct in every browser.
You can use JavaScript to adjust the box:
<svg xmlns="http:/www.w3.org/2000/svg" onload="init()" height="100" width="200">
<style type="text/css">
rect {
stroke:black;
stroke-width:1;
fill:#ccc;
}
</style>
<script type="text/javascript">
var text, rect
var padding = 10
function init() {
text = document.getElementsByTagName("text")[0]
rect = document.getElementsByTagName("rect")[0]
adjustRect()
}
function adjustRect() {
var bbox = text.getBBox()
rect.setAttribute("x",bbox.x - padding)
rect.setAttribute("y",bbox.y - padding )
rect.setAttribute("width",bbox.width + 2*padding)
rect.setAttribute("height",bbox.height + 2*padding)
}
</script>
<g>
<rect x="0" y="0" width="100" height="100" fill="red"></rect>
<text x="50" y="50" font-size="14" fill="blue" text-anchor="middle">Hello</text>
</g>
</svg>
<div>
<button onclick="text.textContent='Goodbye';adjustRect()">change text</button>
</div>
Use an svg filter to draw the background, that will adapt to the size and position of the text. See this answer for a full example.
I decided to play around re-making a nav menu in SVG. It looks quite a bit like this site's nav actually, so nothing much to imagine.
I'm drawing boxes with SVG and then placing text over them, enclosing them both in a link. By attaching a css class to the box, I can set a :hover attritbute, so I can change the background colour when the user hovers over it. The problem is, when the user hovers over the text the color change is reversed, even though the link still works.
How can I make the box change colour as well?
The code looks like this:
<svg width="640px" height="40px"
xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(60 20) ">
<a xlink:href="http://www.apple.com">
<rect width="100" height="40" x="-50" y="-20" rx="5" class="svg_nav" />
<text class= "nav_text" text-anchor="middle" dominant-baseline="mathematical">Home</text>
</a>
</g>
</svg>
What do your style rules look like?
Something like the following should work fine:
<svg width="640px" height="40px"
xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(60 20) ">
<a xlink:href="http://www.apple.com">
<rect width="100" height="40" x="-50" y="-20" rx="5" class="svg_nav" />
<text class= "nav_text" text-anchor="middle" dominant-baseline="mathematical">Home</text>
</a>
</g>
<g transform="translate(166 20) ">
<a xlink:href="http://www.apple.com">
<rect width="100" height="40" x="-50" y="-20" rx="5" class="svg_nav" />
<text class= "nav_text" text-anchor="middle" dominant-baseline="mathematical">Home</text>
</a>
</g>
<style>
g:hover .svg_nav { fill: blue }
g:hover .nav_text { fill: red }
.svg_nav { fill: yellow }
.nav_text { fill: black }
</style>
</svg>