Correct way of changing svg image in svelte - image

In svelte, I have the option of switching between two images, or using css to change the color of the svg image. Which is "better/ best practice"? (also we use tailwind css).
<div class='w-2 h-2'>
{#if condition}
<Image1/> <--white image
{:else}
<Image2/> <--red image
{/if}
</div>
OR
If the default image is white, this passes red to it. The color variable would be text-red or text-white based on some condition.
<div class='w-2 h-2 ${color}'>
<Image1/>
</div>

Svelte's reactivity can take over colour conditions via CSS. We can avoid the if condition.
App.svelte
<script>
import Icon from "./Icon.svelte"
let stroke = "green";
function changeStroke(){
stroke = "red"
}
</script>
<Icon {stroke}/>
<button on:click={changeStroke}>Change</button>
Icon.svelte
<script>
export let stroke = 'white';
</script>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" {stroke} stroke-width="2">
<!-- Big SVG -->
</svg>
See this example REPL

Related

I want to display a spinner before loading the react component in Astro

How can I display a spinner or Skeleton CSS before loading the component
I use client-only for react components in Astro page
my spinner code
<div role="status">
<svg aria-hidden="true" class="w-8 h-8 mr-2 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
</svg>
<span class="sr-only">Loading...</span>
my component
<ToolsDescription client:load/>
Solution
place both components "Spinner" and "ClientComponent" and give them default classes so that only the Spinner is visible.
then once the client component loads, in the client js script, you hide the spinner and show the Client Component by toggling the display property of their style
Simplified example
For the sake of example simplification, I placed the script in the same file, but you can place the styles display toggling once your client component is ready and adapt the proper selector
the <script> will execute on client side
Here how it would look in the .astro component
<>
<div class="spinner">
<Spinner/>
</div>
<div class="mycomponent">
<ClientComponent client:load/>
</div>
</>
<style>
.spinner{
display:block;
}
.card {
display: none;
}
</style>
<script>
document.querySelector(".card").style.display = "block"
document.querySelector(".spinner").style.display = "none"
</script>
Reference Example
Here a reference to a complete example showing the "Spinner" pattern while waiting for client side js component which is intentionally deferred 2 seconds for demo purpose
https://github.com/MicroWebStacks/astro-examples#09_dynamic-imports

Is it possible to justify SVG text using d3js?

I'm wrapping text using M.Bostock's wrap function but can't find a way to justify it.
Is that even possible in d3 ?
If not, is there a way to "mimic" this kind of text disposition ?
EDIT: Thanks to Logikos suggestion, i've found this example from M.Bostock putting a foreignObject inside svg.
Here is the snippet:
var svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500);
svg.append("foreignObject")
.attr("width", 480)
.attr("height", 500)
.append("xhtml:body")
.style("font", "14px 'Helvetica Neue'")
.html("<h1>An HTML Foreign Object in SVG</h1><p>Veeery long text");
Then you just need to add in the CSS:
body {text-align: justify;
text-align-last: start;
}
It is not exactly what your looking for but something I used several years ago. Instead of using that function to mimic wrapping you can instead put html inside svg with the foreignObject tag - http://ajaxian.com/archives/foreignobject-hey-youve-got-html-in-my-svg
As html you can style it however you want, text wrapping, justified etc etc.
I have not worked with d3 or SVG's in over 5 years so it is difficult to remember but thought I'd share this in-case it was of any use.
This is the example markup from the link I posted above:
< ?xml version="1.0" standalone="yes"?>
<svg xmlns = "http://www.w3.org/2000/svg">
<rect x="10" y="10" width="100" height="150" fill="gray"/>
<foreignobject x="10" y="10" width="100" height="150">
<body xmlns="http://www.w3.org/1999/xhtml">
<div>Here is a <strong>paragraph</strong> that requires <em>word wrap</em></div>
</body>
</foreignobject>
<circle cx="200" cy="200" r="100" fill="blue" stoke="red"/>
<foreignobject x="120" y="120" width="180" height="180">
<body xmlns="http://www.w3.org/1999/xhtml">
<div>
<ul>
<li><strong>First</strong> item</li>
<li><em>Second</em> item</li>
<li>Thrid item</li>
</ul>
</div>
</body>
</foreignobject>
</svg>
Please note browser support: http://caniuse.com/#search=foreignObject
Which says it will work in everything other than opera mini. Though there are some limitations in IE and Edge:
1 IE11 and below do not support . 2 IE and Edge do not
support applying SVG filter effects to HTML elements using CSS.
You should check it in IE and Edge, in one place the site says it does not support it, in another it says it supports it somewhat...

Center D3 Piechart in the center of a div, respecting it's dimensions

I'm having some difficulties with centering a piechart I created in D3 in it's parents div. I've set up a JS-fiddle right here: https://jsfiddle.net/86czgLnu/
The problem is that it overflows it's parents dimensions and I want it to scale to fit and be in the center of the parent. I found documentation about preserveAspectRatio and viewBox but wasn't able to fix it with those.
All the code is in the fiddle
Thanks for having a look.
Unfortunately, you can't use percentages inside translate. The best idea would be using JS (D3, in your case) to get the size of the container and translate the group appropriately, by half its width.
Here is your SVG with absolute values for the translate:
<div class="js-graph ct-chart">
<svg width="100%" height="100%">
<g transform="translate(50,50) scale(0.2)">
<path class="slice" fill="#8c564b" d="M1.3532347130578253e-14,-221A221,221,0,1,1,-119.28791713380294,186.04137396256502L0,0Z" original-title=""></path>
<path class="slice" fill="#c49c94" d="M-119.28791713380294,186.04137396256502A221,221,0,0,1,-210.51725450349846,-67.25686252204494L0,0Z"></path>
<path class="slice" fill="#e377c2" d="M-210.51725450349846,-67.25686252204494A221,221,0,0,1,-4.059704139173476e-14,-221L0,0Z"></path>
</g>
</svg>
</div>
An alternative to simulate a translate by percentage is using an inner SVG, as described in this answer by Robert Longson. However, it won't work, because the pie chart is drawn at the origin:
<div class="js-graph ct-chart">
<svg width="100%" height="100%">
<svg x="50%" y="50%">
<g transform="scale(0.2)">
<path class="slice" fill="#8c564b" d="M1.3532347130578253e-14,-221A221,221,0,1,1,-119.28791713380294,186.04137396256502L0,0Z" original-title=""></path>
<path class="slice" fill="#c49c94" d="M-119.28791713380294,186.04137396256502A221,221,0,0,1,-210.51725450349846,-67.25686252204494L0,0Z"></path>
<path class="slice" fill="#e377c2" d="M-210.51725450349846,-67.25686252204494A221,221,0,0,1,-4.059704139173476e-14,-221L0,0Z"></path>
</g>
</svg>
</svg>
</div>
PS: scale is part of the "transform" attribute.

Image mask in Mozilla + foreignObject + Ajax

http://continent-news.info/page_20.html
In the left column of news, they opens in a popup window, and loaded with Ajax.
<div class="ukraine_mask1">
<svg height="116px" width="142px">
<defs>
<mask id="ukraine_mask1" maskContentUnits="userSpaceOnUse" maskUnits="userSpaceOnUse">
<image xlink:href="mask/ukraine_mask1.png" height="116px" width="142px">
</mask>
</defs>
<foreignObject class="recov_ukraine_mask1" style="mask: url(#ukraine_mask1);" height="100%" width="100%">
<div class="element_mask mask1_ukraine">
<img src="../inf_images/small/7812_8926.jpeg">
</div>
</foreignObject>
</svg>
</div>
problem in Mozilla:
Some news used map with a mask, the first time the mask works well. But if I click another news with mask, they does not want to re-use mask... =( If I press again the first news, it will work.
The second time, does not want to re-use =(
If in firebug disable / apply
mask: url ("# ukraine_mask1")
in
foreignObject class = "recov_ukraine_mask1"
it will work again ...
Maybe someone have an idea how to solve this problem?
I tried to add a simple style in СSS, but does not help = (

onload image go from 0 width to 100px width with easing

I need to "slide in" a (background-)image in a div.
When I load the page, some div with a bg image or image inside it (and overflow?) needs to go from invisible/width=0 to 100px width. This needs to ease in.
Can anyone please help me out with the js?
<div style="overflow:hidden; width:100px; height:40px;">
<img src="someimg.png" height="40" width="100" />
</div>
This uses jquery on document ready.. For easing can use the standard jquery 'linear' but I included the jquery.easing plugin where you can have different easing options.
http://jsfiddle.net/DyW7M/1/
$(document).ready(function () {
$('#makeitlong').animate({ width: '400'}, 2000, 'linear');
});​

Resources