I am trying to center a group that has a d3 tree inside of it. The svg is currently positioned perfectly across the browser and I am just trying to get the dynamically loaded tree to stay in the center of that svg element. All tree elements are within one group and have a zoom listener and have the ability to pan.
<svg width="1535" height="685" overflow-y="hidden" class="overlay">
<g transform="translate(742.5,342.5)scale(1)">
<g class="node" transform="translate(0,25)">
<circle class="nodeCircle" r="4.5" style="fill: rgb(255, 255, 255)</circle>
<text x="10" dy=".35em" class="nodeText" text-anchor="start" style="fill-opacity: 1;"></text>
<text x="10" dy="1.5em" class="nodeText" text-anchor="start"></text>
</g>
</g>
</svg>
i hope you understand the concept
first you draw svg with width: 1535 and hight :685
you want to make g element on middle of it
middle of it means half of width(1535/2) and half of height (685/2)
w:767.5 h:342.5
you draw g and transform it. good point but you must set transform to right place, that means on middle of svg to 742.5 and 342.5
so that means you need transform x,y) it more (25,0)
why you set it wrong
<g class="node" transform="translate(0,25)">
it must be
<g class="node" transform="translate(25,0)">
this is little example
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg{
border-style: solid;
border-color: red;
}
}
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<body>
<svg width="200" height="100" overflow-y="hidden" class="overlay">
<g transform="translate(70,20)scale(1)">
<g class="node" transform="translate(30,30)">
<circle class="nodeCircle" r="10" style="fill: black"</circle>
<text x="10" dy=".35em" class="nodeText" text-anchor="start" style="fill-opacity: 1;"></text>
<text x="10" dy="1.5em" class="nodeText" text-anchor="start"></text>
</g>
</g>
</svg>
<svg width="200" height="100" overflow-y="hidden" class="overlay">
<g transform="translate(100,50)scale(1)">
<g class="node" transform="translate(0,0)">
<circle class="nodeCircle" r="10" style="fill: black"</circle>
<text x="10" dy=".35em" class="nodeText" text-anchor="start" style="fill-opacity: 1;"></text>
<text x="10" dy="1.5em" class="nodeText" text-anchor="start"></text>
</g>
</g>
</svg>
<br/>
<svg width="200" height="100" overflow-y="hidden" class="overlay">
<g transform="translate(200,50)scale(1)">
<g class="node" transform="translate(0,0)">
<circle class="nodeCircle" r="10" style="fill: black"</circle>
<text x="10" dy=".35em" class="nodeText" text-anchor="start" style="fill-opacity: 1;"></text>
<text x="10" dy="1.5em" class="nodeText" text-anchor="start"></text>
</g>
</g>
</svg>
<svg width="200" height="100" overflow-y="hidden" class="overlay">
<g transform="translate(100,10)scale(1)">
<g class="node" transform="translate(100,40)">
<circle class="nodeCircle" r="10" style="fill: black"</circle>
<text x="10" dy=".35em" class="nodeText" text-anchor="start" style="fill-opacity: 1;"></text>
<text x="10" dy="1.5em" class="nodeText" text-anchor="start"></text>
</g>
</g>
</svg>
</body>
I want to color the background of svg text similar to background-color in css
I was only able to find documentation on fill, which colors the text itself
Is it even possible?
You could use a filter to generate the background.
<svg width="100%" height="100%">
<defs>
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="yellow" result="bg" />
<feMerge>
<feMergeNode in="bg"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<text filter="url(#solid)" x="20" y="50" font-size="50">solid background</text>
</svg>
No this is not possible, SVG elements do not have background-... presentation attributes.
To simulate this effect you could draw a rectangle behind the text attribute with fill="green" or something similar (filters). Using JavaScript you could do the following:
var ctx = document.getElementById("the-svg"),
textElm = ctx.getElementById("the-text"),
SVGRect = textElm.getBBox();
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
rect.setAttribute("x", SVGRect.x);
rect.setAttribute("y", SVGRect.y);
rect.setAttribute("width", SVGRect.width);
rect.setAttribute("height", SVGRect.height);
rect.setAttribute("fill", "yellow");
ctx.insertBefore(rect, textElm);
The solution I have used is:
<svg>
<line x1="100" y1="100" x2="500" y2="100" style="stroke:black; stroke-width: 2"/>
<text x="150" y="105" style="stroke:white; stroke-width:0.6em">Hello World!</text>
<text x="150" y="105" style="fill:black">Hello World!</text>
</svg>
A duplicate text item is being placed, with stroke and stroke-width attributes. The stroke should match the background colour, and the stroke-width should be just big enough to create a "splodge" on which to write the actual text.
A bit of a hack and there are potential issues, but works for me!
Instead of using a <text> tag, the <foreignObject> tag can be used, which allows for XHTML content with CSS.
No, you can not add background color to SVG elements. You can do it programmatically with d3.
var text = d3.select("text");
var bbox = text.node().getBBox();
var padding = 2;
var rect = self.svg.insert("rect", "text")
.attr("x", bbox.x - padding)
.attr("y", bbox.y - padding)
.attr("width", bbox.width + (padding*2))
.attr("height", bbox.height + (padding*2))
.style("fill", "red");
Answer by Robert Longson (#RobertLongson) with modifications:
<svg width="100%" height="100%">
<defs>
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="yellow"/>
<feComposite in="SourceGraphic" operator="xor"/>
</filter>
</defs>
<text filter="url(#solid)" x="20" y="50" font-size="50"> solid background </text>
<text x="20" y="50" font-size="50">solid background</text>
</svg>
and we have no bluring and no heavy "getBBox" :)
Padding is provided by white spaces in text-element with filter.
It's worked for me
Going further with #dbarton_uk answer, to avoid duplicating text you can use paint-order=stroke style:
<svg>
<line x1="100" y1="100" x2="350" y2="100" style="stroke:grey; stroke-width: 100"/>
<text x="150" y="105" style="stroke:white; stroke-width:0.5em; fill:black; paint-order:stroke; stroke-linejoin:round">Hello World!</text>
</svg>
Note the stroke-linejoin:round which is needed to avoid seeing spikes for the W sharp angle.
You can combine filter with the text.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>SVG colored patterns via mask</title>
</head>
<body>
<svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter x="0" y="0" width="1" height="1" id="bg-text">
<feFlood flood-color="white"/>
<feComposite in="SourceGraphic" operator="xor" />
</filter>
</defs>
<!-- something has already existed -->
<rect fill="red" x="150" y="20" width="100" height="50" />
<circle cx="50" cy="50" r="50" fill="blue"/>
<!-- Text render here -->
<text filter="url(#bg-text)" fill="black" x="20" y="50" font-size="30">text with color</text>
<text fill="black" x="20" y="50" font-size="30">text with color</text>
</svg>
</body>
</html>
For those wondering how to apply padding to a text element when it has a background like in the Robert's answer, do the following:
<svg>
<defs>
<filter x="-0.1" y="-0.1" width="1.2" height="1.2" id="solid">
<feFlood flood-color="#171717"/>
<feComposite in="SourceGraphic" operator="xor" />
</filter>
</defs>
<text filter="url(#solid)" x="20" y="50" font-size="50">Hello</text>
</svg>
In the example above, filter's x and y positions can be used as transform: translate(-10%, -10%) would, and width and height values can be read as 120% and 120%. So we made background 20% bigger, and offsetted it -10%, so background is now 10% bigger on each side of the text.
this is my favorite hack (not sure it should work). It refer an element that is not yet displayed, and it works pretty well
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 620 40" preserveAspectRatio="xMidYMid meet">
<defs>
<filter x="-0.02" y="0" width="1.04" height="1.1" id="removebackground">
<feFlood flood-color="#00ffff"/>
</filter>
</defs>
<!--Draw the text-->
<use xlink:href="#mygroup" filter="url(#removebackground)" />
<g id="mygroup">
<text id="text1" x="9" y="20" style="text-anchor:start;font-size:14px;">custom text with background</text>
<line x1="200" y1="18" x2="200" y2="36" stroke="#000" stroke-width="5"/>
<line x1="120" y1="27" x2="203" y2="27" stroke="#000" stroke-width="5"/>
</g>
</svg>
The previous answers relied on doubling up text and lacked sufficient whitespace.
By using atop and I was able to get the results I wanted.
This example also includes arrows, a common use case for SVG text labels:
<svg viewBox="-105 -40 210 234">
<title>Size Guide</title>
<defs>
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="white"></feFlood>
<feComposite in="SourceGraphic" operator="atop"></feComposite>
</filter>
<marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z"></path>
</marker>
</defs>
<g id="garment">
<path id="right-body" fill="none" stroke="black" stroke-width="1" stroke-linejoin="round" d="M0 0 l30 0 l0 154 l-30 0"></path>
<path id="right-sleeve" d="M30 0 l35 0 l0 120 l-35 0" fill="none" stroke-linejoin="round" stroke="black" stroke-width="1"></path>
<use id="left-body" href="#right-body" transform="scale(-1,1)"></use>
<use id="left-sleeve" href="#right-sleeve" transform="scale(-1,1)"></use>
<path id="collar-right-top" fill="none" stroke="black" stroke-width="1" stroke-linejoin="round" d="M0 -6.5 l11.75 0 l6.5 6.5"></path>
<use id="collar-left-top" href="#collar-right-top" transform="scale(-1,1)"></use>
<path id="collar-left" fill="white" stroke="black" stroke-width="1" stroke-linejoin="round" d="M-11.75 -6.5 l-6.5 6.5 l30 77 l6.5 -6.5 Z"></path>
<path id="front-right" fill="white" stroke="black" stroke-width="1" d="M18.25 0 L30 0 l0 154 l-41.75 0 l0 -77 Z"></path>
<line x1="0" y1="0" x2="0" y2="154" stroke="black" stroke-width="1" stroke-dasharray="1 3"></line>
<use id="collar-right" href="#collar-left" transform="scale(-1,1)"></use>
</g>
<g id="dimension-labels">
<g id="dimension-sleeve-length">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="85" y1="0" x2="85" y2="120" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="85" y="60" class="dimension" text-anchor="middle" dominant-baseline="middle"> 120 cm</text>
</g>
<g id="dimension-length">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-85" y1="0" x2="-85" y2="154" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="-85" y="77" text-anchor="middle" dominant-baseline="middle" class="dimension"> 154 cm</text>
</g>
<g id="dimension-sleeve-to-sleeve">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-65" y1="-20" x2="65" y2="-20" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="0" y="-20" text-anchor="middle" dominant-baseline="middle" class="dimension"> 130 cm </text>
</g>
<g title="Back Width" id="dimension-back-width">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-30" y1="174" x2="30" y2="174" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="0" y="174" text-anchor="middle" dominant-baseline="middle" class="dimension"> 60 cm </text>
</g>
</g>
</svg>
An obvious workaround to the problem of the blur produced by the filter effect is to render the <text> two times: once for the background (with transparent characters) and once for the characters (without a background filter).
For me, this was the only way to make the text readable in Safari.
<svg width="100%" height="100%">
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="yellow" />
</filter>
<g transform="translate(20, 50)" font-size="50">
<text aria-hidden="true" fill="none" filter="url(#solid)">solid background</text>
<text fill="blue">solid background</text>
</g>
</svg>
The aria-hidden="true" attribute is there to prevent screen readers from speaking the text twice, if the user uses a screen reader.
You can add style to your text:
style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
text-shadow: rgb(255, 255, 255) -2px -2px 0px, rgb(255, 255, 255) -2px 2px 0px,
rgb(255, 255, 255) 2px -2px 0px, rgb(255, 255, 255) 2px 2px 0px;"
White, in this example.
Does not work in IE :)
I'm trying to add some background image to SVG nodes "circle".
I have read a lot of stackoverflow answer and everybody is saying that we need to add a node into a to define our image.
I tried this but my image is not displaying at all.
Here is a fiddle of my code: https://jsfiddle.net/baapu6wz/ .
What did I miss ?
<svg baseProfile="full" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" height="390" width="1629">
<g transform="translate(40,0)">
<g>
<line y2="149.3060251652327" x2="819.8567597731511" y1="222.22245513917517" x1="854.7332277213098" style="stroke: #999;" stroke-width="5"></line>
<line y2="213.47136779636722" x2="768.9096407109324" y1="213.47136779636722" x1="768.9096407109324" style="stroke: #999;" stroke-width="5"></line>
<line y2="213.47136779636722" x2="768.9096407109324" y1="149.3060251652327" x1="819.8567597731511" style="stroke: #999;" stroke-width="5"></line>
</g>
<g>
<g transform="translate(854.7332277213098, 222.22245513917517)">
<circle fill="url(#image1);" fillOpacity="0.5" r="16"></circle>
<text x="20" dy="3">pagx</text>
</g>
<g transform="translate(768.9096407109324, 213.47136779636722)">
<circle fill="url(#image1);" fillOpacity="0.5" r="10"></circle>
<text x="20" dy="3">xzreds</text>
</g>
<g transform="translate(819.8567597731511, 149.3060251652327)">
<circle fill="url(#image1);" fillOpacity="0.5" r="14"></circle>
<text x="20" dy="3">jzkcwv</text>
</g>
</g>
</g>
<defs>
<pattern width="16" height="16" patternUnits="userSpaceOnUse" y="0" x="0" id="image1">
<image xlink:href="https://www.google.fr/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png" height="16" width="16" y="0" x="0"></image>
</pattern>
</defs>
You have a typo.
fill="url(#image1);"
should be
fill="url(#image1)"
Remove the semicolon.
https://jsfiddle.net/baapu6wz/1/
I'm using Chrome 49.0.2623.87 (64-bit) on Ubuntu 15.10. Doesn't work in Firefox either.
I have the following code using svg.js:
function blockmouseenterHandler(){
console.debug('mouseenter')
var mask = anatomy.frame.rect(100,100).move(0,0).addClass('hovermask').fill({ color: '#000'});
this.maskWith(mask);
}
The mask/defs it creates:
<defs id="SvgjsDefs1000">
<clipPath id="SvgjsClipPath1022">
<rect id="SvgjsRect1023" width="685.528361111111" height="692.5839166666665" x="0" y="0"></rect>
</clipPath>
<clipPath id="SvgjsClipPath1040">
<rect id="SvgjsRect1041" width="1452.812972222222" height="128.13947222222222" x="0" y="0"></rect>
</clipPath>
<clipPath id="SvgjsClipPath1057">
<rect id="SvgjsRect1058" width="1071.834138888889" height="128.13947222222225" x="0" y="0"></rect>
</clipPath>
<mask id="SvgjsMask1062">
<rect id="SvgjsRect1061" width="100" height="100" x="0" y="0" class="hovermask" fill="#000000"></rect>
</mask>
</defs>
The masked element:
<g id="SvgjsG1027" transform="matrix(1,0,0,1,810.1224365234375,191.731201171875)" class="block" clip-path="url("#SvgjsClipPath1040")" mask="url("#SvgjsMask1062")">
<rect id="SvgjsRect1028" width="1452.812972222222" height="128.13947222222222" x="0" y="0" fill="#dddddd" stroke-width="0" opacity="0.5"></rect>
<g id="SvgjsG1029" transform="matrix(1,0,0,1,0,0)">
<rect id="SvgjsRect1030" width="1452.81298828125" height="128.13946533203125" class="svg_select_boundingRect svg_select_points"></rect>
<circle id="SvgjsCircle1031" r="3.5" cx="0" cy="0" class="svg_select_points_lt svg_select_points"></circle>
<circle id="SvgjsCircle1032" r="3.5" cx="1452.81298828125" cy="0" class="svg_select_points_rt svg_select_points"></circle>
<circle id="SvgjsCircle1033" r="3.5" cx="1452.81298828125" cy="128.13946533203125" class="svg_select_points_rb svg_select_points"></circle>
<circle id="SvgjsCircle1034" r="3.5" cx="0" cy="128.13946533203125" class="svg_select_points_lb svg_select_points"></circle>
<circle id="SvgjsCircle1035" r="3.5" cx="726.406494140625" cy="0" class="svg_select_points_t svg_select_points"></circle>
<circle id="SvgjsCircle1036" r="3.5" cx="1452.81298828125" cy="64.06973266601562" class="svg_select_points_r svg_select_points"></circle>
<circle id="SvgjsCircle1037" r="3.5" cx="726.406494140625" cy="128.13946533203125" class="svg_select_points_b svg_select_points"></circle>
<circle id="SvgjsCircle1038" r="3.5" cx="0" cy="64.06973266601562" class="svg_select_points_l svg_select_points"></circle>
<circle id="SvgjsCircle1039" r="3.5" cx="726.406494140625" cy="20" class="svg_select_points_rot"></circle>
</g>
<text id="SvgjsText1042" font-family="Ubuntu" font-size="120" text-anchor="middle" fill="#000000" alignment-baseline="central" width="1452.812972222222" height="128.13947222222222" x="726.406486111111" y="-35.00838888888889" svgjs:data="{"leading":"1.2em"}">
<tspan id="SvgjsTspan1043" dy="144" x="726.406486111111" svgjs:data="{"newLined":true}">Book Title</tspan>
</text>
</g>
No matter what fill color I use on the mask, it always turns the masked element completely invisible. From what I understand, only a color of #fff should make it completely transparent, #000 should not mask at all, and values in between should give partial transparency, correct?
Update: https://jsfiddle.net/cmuyebma/
Your mask consists of a 100x100 black rectangle. Black in a mask represents transparent.
So you are masking your target element with a mask that represents transparent. So it becomes invisible.
If you want a 100x100 section of your target element to be visible, then you should make the mask rectangle white.
If you want a 100x100 hole in your target element, then you should have a completely white mask with a 100x100 black rectangle on top (representing the hole).
I search everywhere and I didn't understand/found how to do what I want.
I Have 2 svg files who represent somes UML diagrams generated by Visual Paradigm for UML, they have similar objects. For exemple 'FileSource.svg' and 'FileDestination.svg', both of them have an object 'A' who is on differents positions for each.
I would like that when you click on 'A' in 'FileSource.svg' that return 'A' in 'FileDestination.svg' with an hightlight on 'A' to see where it's in the diagram 'FileDestination.svg.
Here is the jsfiddle : http://jsfiddle.net/jim987/rJk54/
But I don't find how to create 2 files with jsfiddle, so the linking part don't work..
First I tried to link the similar objects, there is the code for one object in diagram :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN' 'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
<svg fill-opacity="0" xmlns:xlink="http://www.w3.org/1999/xlink" color-rendering="auto" color-interpolation="auto" stroke="rgb(0,0,0)" text-rendering="auto" stroke-linecap="square" width="1267" stroke-miterlimit="10" stroke-opacity="0" shape-rendering="auto" fill="rgb(0,0,0)" stroke-dasharray="none" font-weight="normal" stroke-width="1" height="626" xmlns="http://www.w3.org/2000/svg" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12" stroke-dashoffset="0" image-rendering="auto">
<defs id="genericDefs"/>
<g>
<defs id="defs1">
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath7">
<path d="M-7 -7 L101 -7 L101 51 L-7 51 L-7 -7 Z"/>
</clipPath>
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath10">
<path d="M0 0 L90 0 L90 15 L0 15 L0 0 Z"/>
</clipPath>
</defs>
<g font-size="11" transform="translate(1173,2)" fill-opacity="1" fill="rgb(255,192,255)" text-rendering="geometricPrecision" font-family="sans-serif" stroke="rgb(255,192,255)" font-weight="bold" stroke-opacity="1">
<a xlink:href="FileDestination.svg#A_Object_FileDestination" xlink:title="object definition">
<rect x="0" width="90" height="40" y="0" clip-path="url(#clipPath7)" stroke="none"/>
</a>
</g>
<g font-size="11" stroke-linecap="butt" transform="translate(1173,2)" fill-opacity="1" fill="black" text-rendering="geometricPrecision" font-family="sans-serif" stroke-linejoin="round" stroke="black" font-weight="bold" stroke-opacity="1" stroke-miterlimit="0">
<rect fill="none" x="0" width="90" height="40" y="0" clip-path="url(#clipPath7)"/>
</g>
<g font-size="11" transform="translate(1173,2)" fill-opacity="1" fill="black" text-rendering="geometricPrecision" font-family="sans-serif" stroke="black" font-weight="bold" stroke-opacity="1">
<a xlink:title="object def">
<text x="21" xml:space="preserve" y="12" clip-path="url(#clipPath10)" stroke="none">Object A</text>
</a>
<line y2="12" fill="none" x1="21" clip-path="url(#clipPath10)" x2="66" y1="12"/>
</g>
</g>
</svg>
Object A in FileDestination.svg :
<g font-size="11" transform="translate(712,44)" fill-opacity="1" fill="rgb(255,192,255)" text-rendering="geometricPrecision" font-family="sans-serif" stroke="rgb(255,192,255)" font-weight="bold" stroke-opacity="1">
<rect id="A_Object_FileDestination" x="0" width="90" height="40" y="0" clip-path="url(#clipPath13)" stroke="none"/>
</g>
The problem is : when I creates this link my rectangle color become black.. do you know why ?
Also is it possible to link my object with the transform defined ? (I saw it in the doc)
like this :
FileDestination.svg#svgView(transform(translate(712,44)))
Because I added the id for each rectangle, when svg files are generate there isn't any ids, just the transforms.
The translate corresponding at the transform of A in FileDestination, but when I tried it, I just have a blank before my diagram..
And Finally, I have no idea, how to do my animation to target the destination of the link. Certainly in JavaScript or with d3.js ? with actionListener ? but how ? because objects are not in the same page. And I do not how to handle the fact that the objects aren't in the same page.
Thanks by advance for yours answers :))