Babel's "replaceWithMultiple" adds unnecessary parentheses - javascript

Please check it out the gist bellow. I'm confused I would expect the same output but without the parentheses and ,. Any clue what I'm doing wrong?
https://astexplorer.net/#/gist/7f499680fcd4aaaba9af215afe42de80/c91228b082de80ef2c57e9c1960b22f884d1e694
E.g
Babel plugin:
export default function (babel) {
const { types: t } = babel;
return {
name: "ast-transform", // not required
visitor: {
JSXElement(path) {
if (path.node.openingElement.name.name === "defs") {
path.replaceWithMultiple(
path.node.children.filter(t.isJSXElement)
);
}
},
}
};
}
Actual:
<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="72" height="72" fill="white" />
<path d="M68.81 0H34.23C34.23 4.14003 35.8746 8.11049 38.8021 11.0379C40.2516 12.4875 41.9724 13.6373 43.8663 14.4218C45.7602 15.2062 47.7901 15.61 49.84 15.61H56.21V21.76C56.2127 25.8966 57.8571 29.8629 60.7821 32.7879C63.7071 35.7129 67.6734 37.3574 71.81 37.36V3C71.81 2.20435 71.4939 1.44129 70.9313 0.87868C70.3687 0.31607 69.6057 0 68.81 0V0Z" fill="#2684FF" />
<path d="M51.7 17.23H17.12C17.1226 21.3666 18.7671 25.3329 21.6921 28.2579C24.617 31.1829 28.5834 32.8273 32.72 32.83H39.09V39C39.0953 43.1366 40.7423 47.1019 43.6691 50.025C46.596 52.9481 50.5634 54.59 54.7 54.59V20.23C54.7 19.4343 54.3839 18.6713 53.8213 18.1087C53.2587 17.5461 52.4956 17.23 51.7 17.23V17.23Z" fill="url(#paint0_linear)" />
<path d="M34.58 34.45H0C0 38.59 1.64462 42.5605 4.57206 45.4879C7.49951 48.4154 11.47 50.06 15.61 50.06H22V56.21C22.0026 60.3431 23.6443 64.3065 26.565 67.2309C29.4857 70.1553 33.4469 71.8021 37.58 71.81V37.45C37.58 36.6543 37.2639 35.8913 36.7013 35.3287C36.1387 34.7661 35.3757 34.45 34.58 34.45Z" fill="url(#paint1_linear)" />
(
<linearGradient id="paint0_linear" x1="53.96" y1="17.29" x2="39.25" y2="32.46" gradientUnits="userSpaceOnUse">
<stop offset="0.18" stop-color="#0052CC" />
<stop offset="1" stop-color="#2684FF" />
</linearGradient>,
<linearGradient id="paint1_linear" x1="1421.65" y1="1327.85" x2="786.064" y2="1949.52" gradientUnits="userSpaceOnUse">
<stop offset="0.18" stop-color="#0052CC" />
<stop offset="1" stop-color="#2684FF" />
</linearGradient>)
</svg>;
Expected:
<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="72" height="72" fill="white" />
<path d="M68.81 0H34.23C34.23 4.14003 35.8746 8.11049 38.8021 11.0379C40.2516 12.4875 41.9724 13.6373 43.8663 14.4218C45.7602 15.2062 47.7901 15.61 49.84 15.61H56.21V21.76C56.2127 25.8966 57.8571 29.8629 60.7821 32.7879C63.7071 35.7129 67.6734 37.3574 71.81 37.36V3C71.81 2.20435 71.4939 1.44129 70.9313 0.87868C70.3687 0.31607 69.6057 0 68.81 0V0Z" fill="#2684FF" />
<path d="M51.7 17.23H17.12C17.1226 21.3666 18.7671 25.3329 21.6921 28.2579C24.617 31.1829 28.5834 32.8273 32.72 32.83H39.09V39C39.0953 43.1366 40.7423 47.1019 43.6691 50.025C46.596 52.9481 50.5634 54.59 54.7 54.59V20.23C54.7 19.4343 54.3839 18.6713 53.8213 18.1087C53.2587 17.5461 52.4956 17.23 51.7 17.23V17.23Z" fill="url(#paint0_linear)" />
<path d="M34.58 34.45H0C0 38.59 1.64462 42.5605 4.57206 45.4879C7.49951 48.4154 11.47 50.06 15.61 50.06H22V56.21C22.0026 60.3431 23.6443 64.3065 26.565 67.2309C29.4857 70.1553 33.4469 71.8021 37.58 71.81V37.45C37.58 36.6543 37.2639 35.8913 36.7013 35.3287C36.1387 34.7661 35.3757 34.45 34.58 34.45Z" fill="url(#paint1_linear)" />
<linearGradient id="paint0_linear" x1="53.96" y1="17.29" x2="39.25" y2="32.46" gradientUnits="userSpaceOnUse">
<stop offset="0.18" stop-color="#0052CC" />
<stop offset="1" stop-color="#2684FF" />
</linearGradient>
<linearGradient id="paint1_linear" x1="1421.65" y1="1327.85" x2="786.064" y2="1949.52" gradientUnits="userSpaceOnUse">
<stop offset="0.18" stop-color="#0052CC" />
<stop offset="1" stop-color="#2684FF" />
</linearGradient>
</svg>;
Cheers,
EDIT: One idea I got is to use the Fragments
path.replaceWith(
t.jsxFragment(
t.jsxOpeningFragment(),
t.jsxClosingFragment(),
path.node.children.filter(t.isJSXElement)
)
);
with the result
<>
<linearGradient
id="prefix__paint0_linear"
x1={53.96}
y1={17.29}
x2={39.25}
y2={32.46}
gradientUnits="userSpaceOnUse"
>
<stop offset={0.18} stopColor="#0052CC" />
<stop offset={1} stopColor="#2684FF" />
</linearGradient>
<linearGradient
id="prefix__paint1_linear"
x1={1421.65}
y1={1327.85}
x2={786.064}
y2={1949.52}
gradientUnits="userSpaceOnUse"
>
<stop offset={0.18} stopColor="#0052CC" />
<stop offset={1} stopColor="#2684FF" />
</linearGradient>
</>
Better, but not entirety what I want.

You could try to use replaceInline instead; it doesn't add any parentheses or comma's in your AST Explorer example.
My guess is that this is caused by the leading and trailing comments that are added when using replaceWithMultiple. Check out the source code here:
https://github.com/babel/babel/blob/0345c1bc1ded6af8d66f8605e6fdbeeb9b70c5b3/packages/babel-traverse/src/path/replacement.js#L50
and compare it to the source of replaceInline:
https://github.com/babel/babel/blob/0345c1bc1ded6af8d66f8605e6fdbeeb9b70c5b3/packages/babel-traverse/src/path/replacement.js#L266

Related

Is there a way to add a custom SVG path to act as a cursor in a webpage?

I'm familiar with binding the 'mousemove' event (shown below) to a div and moving the div around the page while hiding the real cursor, but is there a way to take this further, in order to change the shape of the circle to an SVG path, and to drag the SVG path around the page instead of a circle?
document.onmousemove = function(e) {
document.getElementsByClassName('cursor')[0].style.setProperty('--x',(e.clientX)+'px');
document.getElementsByClassName('cursor')[0].style.setProperty('--y',(e.clientY)+'px');
}
body {
background-color: black;
cursor: none;
}
.cursor {
content:"";
position:absolute;
z-index:999;
top:0;
left:0;
right:0;
bottom:0;
background:
radial-gradient(farthest-side ,#fff 95%,transparent 100%)
calc(var(--x) - .75em) calc(var(--y) - .75em)/1.5em 1.5em fixed no-repeat;
mix-blend-mode:difference;
pointer-events: none;
cursor: none;
}
<body>
<div class="cursor">
</div>
</body>
It worked for me.
document.onmousemove = function(e) {
document.getElementsByClassName('cursor')[0].style.setProperty('--x',(e.clientX)+'px');
document.getElementsByClassName('cursor')[0].style.setProperty('--y',(e.clientY)+'px');
}
body {
background-color: black;
cursor: none;
}
.cursor {
content:"";
position:absolute;
top: var(--y);
left: var(--x);
pointer-events: none;
cursor: none;
}
<body>
<body>
<svg width="3.5%" class="cursor" version="1.1" viewBox="0 0 60 210" xmlns="http://www.w3.org/2000/svg">
<title>Sword</title>
<desc>https://www.sololearn.com/Profile/8896242</desc>
<defs>
<linearGradient id="edge_grad">
<stop offset="0%" stop-color="white" />
<stop offset="10%" stop-color="grey" />
<stop offset="100%" stop-color="black" />
</linearGradient>
<linearGradient id="dol_grad">
<stop offset="0%" stop-color="black" />
<stop offset="50%" stop-color="grey" />
<stop offset="100%" stop-color="black" />
</linearGradient>
<linearGradient id="gard_grad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="white" />
<stop offset="20%" stop-color="grey" />
<stop offset="100%" stop-color="black" />
</linearGradient>
<radialGradient id="ruby_grad">
<stop offset="0%" stop-color="#900020" />
<stop offset="50%" stop-color="#f50029" />
<stop offset="100%" stop-color="#7b001c" />
</linearGradient>
<linearGradient id="handle_grad">
<stop offset="0%" stop-color="#cc6600" />
<stop offset="20%" stop-color="#753313" />
<stop offset="100%" stop-color="#4d220e" />
</linearGradient>
<linearGradient id="pommel_grad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#5b6669" />
<stop offset="20%" stop-color="#434b4d" />
<stop offset="70%" stop-color="#23282b" />
<stop offset="100%" stop-color="#000000" />
</linearGradient>
</defs>
<g stroke="black">
<path id="edge" fill="url(#edge_grad)" d="M20,150 v-130 l10,-20 l10,20 v130 l-10,-2.5 z" />
<path id="dol" fill="url(#dol_grad)" d="M28,148 v-130 q2,-5 4,0 v130 l-2,-1 z" />
<path id="gard" fill="url(#gard_grad)" d="M0,150 h20 l10,-2.5 l10,2.5 h20 l-25,10 q-5,1.5 -10,0 z" />
<g id="ruby">
<path fill="url(#ruby_grad)" d="M20,150 l10,-2.5 l10,2.5 l-5,10 q-5,1.5 -10,0 z" />
<line x1="20" y1="150" x2="30" y2="154" />
<line x1="30" y1="147.5" x2="30" y2="154" />
<line x1="40" y1="150" x2="30" y2="154" />
<line x1="25" y1="160" x2="30" y2="154" />
<line x1="35" y1="160" x2="30" y2="154" />
</g>
<g id="handle">
<path fill="url(#handle_grad)" d="M25,160 v30 q5,2.5 10,0 v-30 q-5,1.5 -10,0 z" />
<line x1="25" y1="162" x2="30" y2="161" />
<line x1="25" y1="165" x2="35" y2="162" />
<line x1="25" y1="168" x2="35" y2="165" />
<line x1="25" y1="171" x2="35" y2="168" />
<line x1="25" y1="174" x2="35" y2="171" />
<line x1="25" y1="177" x2="35" y2="174" />
<line x1="25" y1="180" x2="35" y2="177" />
<line x1="25" y1="183" x2="35" y2="180" />
<line x1="25" y1="186" x2="35" y2="183" />
<line x1="25" y1="189" x2="35" y2="186" />
<line x1="27" y1="191" x2="35" y2="189" />
</g>
<g id="pommel">
<path fill="url(#pommel_grad)" d="M25,190 l-5,13 l10,7 l10,-7 l-5,-13 q-5,2.5 -10,0 z" />
<line x1="30" y1="191.5" x2="30" y2="210" />
<line x1="20" y1="203" x2="40" y2="203" />
</g>
</g>
</svg>
</div>
</body>

SVG gradient color

Hi I'm working with SVG here I trying to add the gradient to SVG like this
white and grey gradient but I unable to achieve the desired output. Can anyone point me in the right direction.
<svg viewBox="0 0 400 400">
<defs>
<linearGradient id="GradientRepeat" x1="0" y1="1" x2="0" y2="0" spreadMethod="repeat">
<stop offset="0.05" stop-color="#fff" stop-opacity="0"/>
<stop offset="1" stop-color="#777" stop-opacity="1"/>
</linearGradient>
</defs>
<circle class="sub-menu-circle" cx="0" cy="200" r="160" fill="url(#GradientRepeat)" />
</svg>
<svg viewBox="0 0 700 700" class="bubble-svg">
<defs>
<linearGradient id="GradientRepeat" x1="0" y1="1" x2="0" y2="0" spreadMethod="repeat" gradientTransform="rotate(170)">
<stop offset="0%" stop-color="#fff" stop-opacity="0"/>
<stop offset="10%" stop-color="#bdbdbd" stop-opacity="0.5"/>
<stop offset="20%" stop-color="#fff" stop-opacity="0"/>
<stop offset="30%" stop-color="#bdbdbd" stop-opacity="0.5"/>
<stop offset="40%" stop-color="#fff" stop-opacity="0"/>
<stop offset="50%" stop-color="#bdbdbd" stop-opacity="1"/>
<stop offset="60%" stop-color="#fff" stop-opacity="0"/>
<stop offset="70%" stop-color="#bdbdbd" stop-opacity="0.5"/>
<stop offset="80%" stop-color="#bdbdbd" stop-opacity="0"/>
<stop offset="100%" stop-color="#fbfbfb" stop-opacity="0.5"/>
</linearGradient>
</defs>
<circle class="sub-menu-circle" cx="0" cy="200" r="160" fill="url(#GradientRepeat)" />
</svg>
Fine-tuning the rendering of shades of gray and white colors depends on which video card, browser and operating system you are using.
Therefore, I am sending several options. You can use any option that you prefer or slightly adjust for yourself by changing the colors.
<svg viewBox="0 0 700 700" class="bubble-svg">
<defs>
<linearGradient id="GradientRepeat" x1="0" y1="0" x2="0" y2="1" spreadMethod="repeat" gradientTransform="rotate(170)">
<stop offset="0%" stop-color="#B4B4B5" stop-opacity="1"/>
<stop offset="17%" stop-color="#fff" stop-opacity="0.8"/>
<stop offset="30%" stop-color="#B4B4B5" stop-opacity="0.6"/>
<stop offset="49%" stop-color="#fff" stop-opacity="0.8"/>
<stop offset="61%" stop-color="#B4B4B5" stop-opacity="0.6"/>
<stop offset="80%" stop-color="#fff" stop-opacity="0.8"/>
<stop offset="95%" stop-color="#B4B4B5" stop-opacity="1"/>
</linearGradient>
</defs>
<circle class="sub-menu-circle" cx="0" cy="200" r="160" fill="url(#GradientRepeat)" />
</svg>
2# variant
<svg viewBox="0 0 700 700" class="bubble-svg">
<defs>
<linearGradient id="GradientRepeat" x1="0" y1="0" x2="0" y2="1" spreadMethod="repeat" gradientTransform="rotate(170)">
<stop offset="0%" stop-color="#B4B4B5" stop-opacity="1"/>
<stop offset="17%" stop-color="#F6F6F6" stop-opacity="0.8"/>
<stop offset="30%" stop-color="#B4B4B5" stop-opacity="0.6"/>
<stop offset="49%" stop-color="#F6F6F6" stop-opacity="0.8"/>
<stop offset="61%" stop-color="#B4B4B5" stop-opacity="0.6"/>
<stop offset="80%" stop-color="#F6F6F6" stop-opacity="0.8"/>
<stop offset="95%" stop-color="#B4B4B5" stop-opacity="1"/>
</linearGradient>
</defs>
<circle class="sub-menu-circle" cx="0" cy="200" r="160" fill="url(#GradientRepeat)" />
</svg>
3# variant
<svg viewBox="0 0 700 700" class="bubble-svg">
<defs>
<linearGradient id="GradientRepeat" x1="0" y1="0" x2="0" y2="1" spreadMethod="repeat" gradientTransform="rotate(170)">
<stop offset="0%" stop-color="#ABABAC" stop-opacity="1"/>
<stop offset="17%" stop-color="#fff" stop-opacity="0.8"/>
<stop offset="30%" stop-color="#ABABAC" stop-opacity="0.6"/>
<stop offset="49%" stop-color="#fff" stop-opacity="0.8"/>
<stop offset="61%" stop-color="#ABABAC" stop-opacity="0.6"/>
<stop offset="80%" stop-color="#fff" stop-opacity="0.8"/>
<stop offset="95%" stop-color="#ABABAC" stop-opacity="1"/>
</linearGradient>
</defs>
<circle class="sub-menu-circle" cx="0" cy="200" r="160" fill="url(#GradientRepeat)" />
</svg>
For a more precise adjustment to your taste, it is better to use stop-color and stop-opacity choosing values.
Update
For the method spreadMethod ="repeat" to start working in your example, you need to reduce the gradient coverage by three times. To do this, set x1 ="0" y1 ="0" x2 ="0" y2 ="0.33"
As a result, adjusting the color tones of one wave, we get completely identical copies of it, which facilitates the process compared to the option of a large number of stop-offset
<svg viewBox="0 0 700 700" class="bubble-svg">
<defs>
<linearGradient id="GradientRepeat" x1="0" y1="0" x2="0" y2="0.33"
spreadMethod="repeat" gradientTransform="rotate(170)">
<stop offset="10%" stop-color="#ABABAC" stop-opacity="1"/>
<stop offset="50%" stop-color="#ffffff" stop-opacity="0.8"/>
<stop offset="85%" stop-color="#ABABAC" stop-opacity="1"/>
</linearGradient>
</defs>
<circle class="sub-menu-circle" cx="0" cy="200" r="160" fill="url(#GradientRepeat)" />
</svg>

How to change stroke-width without changing inner radius of the circle [duplicate]

This question already has answers here:
Can you control how an SVG's stroke-width is drawn?
(13 answers)
Closed 3 years ago.
I need to change stroke-width dynamically and I need to keep inner radius of the circle unchangeable.
<g fill="none" :stroke-width="brightness * 60" ...
How can I achieve that effect ?
svg that I use is below. I want to create rainbow circle and the width of the circle has to be changed depending on the chosen brightness.
The width changes correctly but I would like to keep inner radius unchangeable.
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="-35 -35 270 270">
<defs>
<linearGradient id="redyel" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#ff0000" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#ffff00" :stop-opacity="saturation"/>
</linearGradient>
<linearGradient id="yelgre" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#ffff00" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#00ff00" :stop-opacity="saturation"/>
</linearGradient>
<linearGradient id="grecya" gradientUnits="objectBoundingBox" x1="1" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#00ff00" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#00ffff" :stop-opacity="saturation"/>
</linearGradient>
<linearGradient id="cyablu" gradientUnits="objectBoundingBox" x1="1" y1="1" x2="0" y2="0">
<stop offset="0%" stop-color="#00ffff" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#0000ff" :stop-opacity="saturation"/>
</linearGradient>
<linearGradient id="blumag" gradientUnits="objectBoundingBox" x1="0" y1="1" x2="0" y2="0">
<stop offset="0%" stop-color="#0000ff" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#ff00ff" :stop-opacity="saturation"/>
</linearGradient>
<linearGradient id="magred" gradientUnits="objectBoundingBox" x1="0" y1="1" x2="1" y2="0">
<stop offset="0%" stop-color="#ff00ff" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#ff0000" :stop-opacity="saturation"/>
</linearGradient>
</defs>
<g fill="none" :stroke-width="brightness * 60" transform="translate(100,100)">
<path d="M 0,-100 A 100,100 0 0,1 86.6,-50" stroke="url(#redyel)"/>
<path d="M 86.6,-50 A 100,100 0 0,1 86.6,50" stroke="url(#yelgre)"/>
<path d="M 86.6,50 A 100,100 0 0,1 0,100" stroke="url(#grecya)"/>
<path d="M 0,100 A 100,100 0 0,1 -86.6,50" stroke="url(#cyablu)"/>
<path d="M -86.6,50 A 100,100 0 0,1 -86.6,-50" stroke="url(#blumag)"/>
<path d="M -86.6,-50 A 100,100 0 0,1 0,-100" stroke="url(#magred)"/>
</g>
<circle cx="100" cy="100" r="65" :fill="hsla"/>
</svg>
The inner radius of a circle's stroke is always half the stroke width less than the radius, so to keep the inner radius in the same place you have to increase the radius of the circle by half of its stroke, like: https://jsfiddle.net/f3wctoyL/1/
<svg width="400" height="400">
<circle id="a" cx="200" cy="200" r="100" />
<circle id="b" cx="200" cy="200" r="110" />
<circle id="c" cx="200" cy="200" r="105" />
</svg>
The strokes on circles b and c have inner radii of 100.
just call this function. have a nice day
function strokeInside(svgIdSelector, strokeValue) {
let svgElement = document.getElementById(svgIdSelector),
svgRect = svgElement.getBBox(),
scale = ( (svgRect.height - strokeValue) * 100/svgRect.height )/100;
if (scale < 0.5) {
console.error("max stroke value = " + [svgRect.height / 2]);
return false;
}
svgElement.setAttributeNS(null, "stroke-width", strokeValue/scale);
svgElement.setAttributeNS(null, "transform", "translate(100,100) scale(" + scale + ")");
return true;
}
strokeInside("group", 70);
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="-35 -35 270 270">
<defs>
<linearGradient id="redyel" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#ff0000" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#ffff00" :stop-opacity="saturation"/>
</linearGradient>
<linearGradient id="yelgre" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#ffff00" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#00ff00" :stop-opacity="saturation"/>
</linearGradient>
<linearGradient id="grecya" gradientUnits="objectBoundingBox" x1="1" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#00ff00" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#00ffff" :stop-opacity="saturation"/>
</linearGradient>
<linearGradient id="cyablu" gradientUnits="objectBoundingBox" x1="1" y1="1" x2="0" y2="0">
<stop offset="0%" stop-color="#00ffff" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#0000ff" :stop-opacity="saturation"/>
</linearGradient>
<linearGradient id="blumag" gradientUnits="objectBoundingBox" x1="0" y1="1" x2="0" y2="0">
<stop offset="0%" stop-color="#0000ff" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#ff00ff" :stop-opacity="saturation"/>
</linearGradient>
<linearGradient id="magred" gradientUnits="objectBoundingBox" x1="0" y1="1" x2="1" y2="0">
<stop offset="0%" stop-color="#ff00ff" :stop-opacity="saturation"/>
<stop offset="100%" stop-color="#ff0000" :stop-opacity="saturation"/>
</linearGradient>
</defs>
<g id="group" fill="none" stroke-width="1" transform="translate(100,100)">
<path d="M 0,-100 A 100,100 0 0,1 86.6,-50" stroke="url(#redyel)"/>
<path d="M 86.6,-50 A 100,100 0 0,1 86.6,50" stroke="url(#yelgre)"/>
<path d="M 86.6,50 A 100,100 0 0,1 0,100" stroke="url(#grecya)"/>
<path d="M 0,100 A 100,100 0 0,1 -86.6,50" stroke="url(#cyablu)"/>
<path d="M -86.6,50 A 100,100 0 0,1 -86.6,-50" stroke="url(#blumag)"/>
<path d="M -86.6,-50 A 100,100 0 0,1 0,-100" stroke="url(#magred)"/>
</g>
</svg>

How to create a joystick for camera control

Hey I am trying to build a joystick which is well understood and can be used by elders. The joystick need to have 4 directions: Left,Right,Top and Down and also has a pause button in the middle.
This joystick is need to be used for moving a camera.
I have found a code in the web which create for me an svg joystick.
The problem is that this joystick isn't easy to used ,and when you pressed on a direction you don't know if you click on it or not.
Also when you click on the center for stop action you don't have a feedeback for clicking.
I am looking for alternative or improvement for my current joystick.
How can I improve my current controller so I will have a feedback for clicking in svg. Can I create a stick in svg so I will know to which direction I am pointing right now?
I would be happy if someone can help me with this controller,
thanks in advance.
Edit:
I need a real visual feedback for each arrow and the stop button. If any changes are required for current svg, it is welcome.
#arrowRight:hover,
#arrowLeft:hover,
#arrowDown:hover,
#arrowUp:hover{
fill:blue;
}
<div id="joystick" style="width:20%">
<svg width="100%" height="100%" viewBox="0 0 100 100">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(16,16,16);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(240,240,240);stop-opacity:1" />
</linearGradient>
<linearGradient id="grad2" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(240,240,240);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(16,16,16);stop-opacity:1" />
</linearGradient>
<linearGradient id="grad3" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(168,168,168);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(239,239,239);stop-opacity:1" />
</linearGradient>
</defs>
<circle cx="50" cy="50" r="50" fill="url(#grad1)" />
<circle cx="50" cy="50" r="47" fill="url(#grad2)" stroke="black" stroke-width="1.5px" />
<circle cx="50" cy="50" r="44" fill="url(#grad3)" />
<circle cx="50" cy="50" r="20" fill="#cccccc" stroke="black" stroke-width="1px" />
<path id="arrowUp" d="M50,14 54,22 46,22Z" fill="rgba(0,0,0,0.8)" />
<path id="arrowDown" d="M50,86 54,78 46,78Z" fill="rgba(0,0,0,0.8)" />
<path id="arrowLeft" d="M14,50 22,54 22,46Z" fill="rgba(0,0,0,0.8)" />
<path id="arrowRight" d="M86,50 78,54 78,46Z" fill="rgba(0,0,0,0.8)" />
</svg>
</div>
You can add an onclick function to each path. Send the direction as a parameter to this function.
function click(elem, direction) {
var arrows = document.getElementsByClassName("arrow");
//reset all arrows
for (let i = 0; i < arrows.length; i++) {
arrows[i].style.fill = "rgba(0,0,0,0.8)";
}
//Set the clicked arrow to red
elem.style.fill = "red";
};
#arrowRight:hover,
#arrowLeft:hover,
#arrowDown:hover,
#arrowUp:hover {
fill: blue;
}
<div id="joystick" style="width:20%">
<svg width="100%" height="100%" viewBox="0 0 100 100">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(16,16,16);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(240,240,240);stop-opacity:1" />
</linearGradient>
<linearGradient id="grad2" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(240,240,240);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(16,16,16);stop-opacity:1" />
</linearGradient>
<linearGradient id="grad3" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(168,168,168);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(239,239,239);stop-opacity:1" />
</linearGradient>
</defs>
<circle cx="50" cy="50" r="50" fill="url(#grad1)" />
<circle cx="50" cy="50" r="47" fill="url(#grad2)" stroke="black" stroke-width="1.5px" />
<circle cx="50" cy="50" r="44" fill="url(#grad3)" />
<circle cx="50" cy="50" r="20" fill="#cccccc" stroke="black" stroke-width="1px" />
<path id="arrowUp" class="arrow" d="M50,14 54,22 46,22Z" fill="rgba(0,0,0,0.8)" onclick="click(this, 'up')" />
<path id="arrowDown" class="arrow" d="M50,86 54,78 46,78Z" fill="rgba(0,0,0,0.8)" onclick="click(this,'down')" />
<path id="arrowLeft" class="arrow" d="M14,50 22,54 22,46Z" fill="rgba(0,0,0,0.8)" onclick="click(this,'left')" />
<path id="arrowRight" class="arrow" d="M86,50 78,54 78,46Z" fill="rgba(0,0,0,0.8)" onclick="click(this,'right')" />
</svg>
</div>

Multiple colors in one single character(svg)

I'm looking for a solution in SVG that enables several colors in one single character without any visual gradients.
Here is an example of how I want the result to look like
Here is the best solution that I can come up with. This works perfect with only 2 colors, but more colors doesn't give the result that I want.
<svg width="200" height="80" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="bicolored" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="33%" stop-color="blue"/>
<stop offset="33%" stop-color="red"/>
<stop offset="66%" stop-color="orange"/>
</linearGradient>
</defs>
<text font-family="Arial" font-size="35" font-weight="bold" x="0" y="45" fill="url(#bicolored)">6
</text>
</svg>
Use multiple stops of the same colour if you don't want gradients.
<svg width="200" height="80" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="bicolored" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="33%" stop-color="blue"/>
<stop offset="33%" stop-color="red"/>
<stop offset="66%" stop-color="red"/>
<stop offset="66%" stop-color="orange"/>
</linearGradient>
</defs>
<text font-family="Arial" font-size="35" font-weight="bold" x="0" y="45" fill="url(#bicolored)">6
</text>
</svg>

Categories

Resources