How to create a Radial Dial menu in a Website? - wordpress

I am trying to create a Radial Dial type menu, similar to the picture here (the highlighted top section should be on hover):
Googling about radial menu or radial dial menu doesn't result to anything similar to this.
I am currently using Elementor pro with WordPress. So I can add custom HTML/CSS/JavaScript as well if required.
I was thinking of creating 3-4 buttons and then somehow try to transform them into a semi circle and then position them together. However that creates a lot of manual effort of resizing everything if a menu items is added/removed. Also, it will be a nightmare to make the website responsive.

You could use SVG for your radial buttons, with a little js to handle the onclicks.
I created this svg code from adobe illustrator, but you may be able to find online svg code generators if you don't have adobe illustrator.
See example below with css hovers using ids on PATHs... you can use classes and other html attributes to get your desired result...
PATH {
fill: gray;
stroke: #000;
stroke-miterlimit: 10;
}
PATH:hover {
cursor: pointer;
}
PATH#option_a:hover {
fill: red;
}
PATH#option_b:hover {
fill: green;
}
PATH#option_c:hover {
fill: blue;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1200">
<path id="option_a" d="M600.5,104.1c-276.1,0-500,223.9-500,500h100c0-220.9,179.1-400,400-400s400,179.1,400,400h100c0-276.1-223.9-500-500-500Z"/>
<path id="option_b" d="M600.5,1004.1v100c276.1,0,500-223.9,500-500h-100c0,220.9-179.1,400-400,400Z"/>
<path id="option_c" d="M200.5,604.1H100.5c0,276.1,223.9,500,500,500v-100c-220.9,0-400-179.1-400-400Z"/>
</svg>
Answer to your comment, yeah sure so many things are possible with SVG. Though I am not guna lie, having Adobe Illustrator as tool makes SVG design a lot easier!
So I added arrows to my original SVG code (using Adobe Illustrator), and then created new SVG file code including arrows. From this new SVG code I took the d attribute from my paths and added them to my original SVG paths as a data-d attribute...
Then using a little jQuery, on path hover, I switch the current d attribute with my data-d attribute...
// on ready
$(function() {
// on any segment mouse enter path
$('.segment').on('mouseenter', function(e) {
// temporally store hover-state data-d attribute coordinates
let d = $(this).attr('data-d');
// override data-d attribute value with original d attribute coordinates
$(this).attr('data-d', $(this).attr('d'));
// set d attribute with temporally stored hover-state coordinates
$(this).attr('d', d);
// on any segment mouse leave path
}).on('mouseleave', function(e) {
// temporally store original-state data-d attribute coordinates
let d = $(this).attr('data-d');
// override data-d attribute value with hover-state d attribute coordinates
$(this).attr('data-d', $(this).attr('d'));
// set d attribute with temporally stored original-state coordinates
$(this).attr('d', d);
});
});
SVG {
display: block;
width: 300px;
margin: 0 auto;
}
PATH {
fill: gray;
stroke: #000;
stroke-miterlimit: 10;
}
PATH:hover {
cursor: crosshair;
}
PATH#segment_r:hover {
fill: red;
}
PATH#segment_g:hover {
fill: green;
}
PATH#segment_b:hover {
fill: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1200">
<path
class="segment"
id="segment_r"
d="M600.5,104.1c-276.1,0-500,223.9-500,500h100c0-220.9,179.1-400,400-400s400,179.1,400,400h100c0-276.1-223.9-500-500-500Z"
data-d="M630.4,105l-29.9-29.9L570.6,105c-262.2,15.5-470.1,233-470.1,499.1h100c0-220.9,179.1-400,400-400
s400,179.1,400,400h100C1100.5,338,892.6,120.4,630.4,105z"
/>
<path
class="segment"
id="segment_g"
d="M600.5,1004.1v100c276.1,0,500-223.9,500-500h-100c0,220.9-179.1,400-400,400Z"
data-d="M974.6,935.9c78.4-88.3,125.9-204.5,125.9-331.8h-100c0,220.9-179.1,400-400,400v100
c127.3,0,243.5-47.6,331.8-125.9h42.3V935.9z"
/>
<path
class="segment"
id="segment_b"
d="M200.5,604.1H100.5c0,276.1,223.9,500,500,500v-100c-220.9,0-400-179.1-400-400Z"
data-d="M600.5,1004.1c-220.9,0-400-179.1-400-400h-100c0,127.3,47.6,243.5,125.9,331.8v42.3h42.3
c88.3,78.4,204.5,125.9,331.8,125.9V1004.1z"
/>
</svg>
Here is fiddle version... https://jsfiddle.net/joshmoto/f9wg57u1/
I love SVG code. So much is possible.
My example is probably a little heavy (hence using JS), I'm sure someone could recreate this with pure SVG and CSS.
But Adobe Illustrator makes things so much easier from a visual design point of view when creating SVG's.
Update: I've changed the path hover state cursor to crosshair so
you can see how the segment arrow is also included in the hover area
before mouseleave event.

Related

iframe change elements of a svg in external css file [duplicate]

I'm importing an svg from file using the <object> element
<object data="img/icons/some-svg.svg" type="image/svg+xml"></object>
From the inspect element tool it's hierarchy appears as follows in the browser
<object data="img/icons/some-svg.svg" type="image/svg+xml">
#document
<svg ...>
...
</svg>
</object>
As I want to change the color of the svg how do I access the encapsulated svg component in the object element?
Here's how you insert a style into a document. The rect element has no colour defined in markup, the green colour comes from the javascript injected style rule.
document.styleSheets[0].insertRule('rect { fill: green; }', 0);
<svg viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100"/></svg>
So now we know how to do that how do we use it with an object tag. Well we need to get the object tag. You could either give it an id and get it by its id or try to find it in the DOM e.g.
let o = document.getElementsByTagName('object')[0];
Then you get its contentDocument i.e.
let doc = o.contentDocument;
and you can use that to insert the style as demonstrated above. I.e.
doc.styleSheets[0].insertRule('rect { fill: green; }', 0);
Unfortunately I can't demonstrate this from start to finish because the contentDocument of a data url is null.
svg {
fill: #ff0000;
}
use this css rule to change the color

React-leaflet V3 Polyline animation

I am creating a Polyline component using two positions with Typescript based on the react-leaflet. I want to make an animation from the source to the destination. It should look like something is flowing between source to destination. I'm able to set the animation with CSS Animation however, I have the issue that the transition between the last color( yellow at 100%) and return to the initial position (blue at 0%) is happening very abruptly, not smooth like other changes in between. I want these last changes also smooth like others so that it looks like a continuous flow. Here is my code,
React-leaflet Polyline
<Polyline
key={eachConnection.id}
weight={4}
className="water-flow"
positions={[[source.lat, source.long],[target.lat, target.long]]}
/>
CSS for the Polyline
.water-flow{
stroke: lime;
stroke-width: 3;
animation: 3s ease infinite Anim;
}
#keyframes Anim {
0%{
stroke : blue;
}
2%{
stroke: green;
}
50%{
stroke: red;
}
98%{
stroke: cyan;
}
100%{
stroke: yellow;
}
}
Recently I used React Leaflet Drift Marker https://github.com/hugobarragon/react-leaflet-drift-marker (for animating the marker) combined with Polyline https://react-leaflet.js.org/docs/example-vector-layers/ component (for showing the trail) but the effort is not simple
I found a great Leaflet library that combined animation marker and trail here https://github.com/Igor-Vladyka/leaflet.motion
Here is the demo https://igor-vladyka.github.io/leaflet.motion/
Currently, I only found the library using Vanilla Js (we could use it for any frontend framework like React Js, Vue Js, and Angular Js) but hope that in the near future the library would be available directly for each framework

Icomoon, open-iconic SVG icons not displaying in the blazor page

I'm trying to use Icomoon in my blazor project. I've already downloaded the icons.
HTML
<button class="search__button">
<svg class="search__button__icon">
<use xlink:href="img/icons/symbol-defs.svg#magnifying-glass.svg"></use>
</svg>
</button>
CSS
.search__button {
&__icon {
color: #444444;
width: 1.75rem;
height: 1.75rem;
}
}
The location of the SVG files
The result I'm getting
Am I missing something? I think to have followed what it's said in the documentation.
Thanks for helping
EDIT
In this documentation is says that the svg icon can be used as an image like this:
<img class="nav__level-item__icon" src="img/icons/svg/home.svg" alt="home">
When used like this, it's displaying.
&__icon {
width: 1.75rem;
height: 1.75rem;
fill: #fff; //and/or color: #fff
}
The only problem with using it as an image is that I can't style it. So, at the end, I'm still stuck.
EDIT 2
I tried to implement what's suggested in this blog post. Icons are being displayed, I can't still style them.
According to Microsoft SVG use is a still limited, in this Microsoft document it states
If you place an <svg> tag directly into a component file (.razor), basic image
rendering is supported but many advanced scenarios aren't yet supported. For
example, <use> tags aren't currently respected
If you use a string variable for the xlink:href attribute the icon will render after pre-rendering but would disappear as soon as the Blazor library was loaded in the client, but looks like there is a workaround.
Instead of putting the svg and use tags in the .razor file you can return a MarkupString instead, something like
<i class="icon">
#IconMarkupString
</i>
#code {
[Parameter]
public string IconSprite { get; set; }
private MarkupString IconMarkupString
{
get => new MarkupString($"<svg class='icon-sprite'><use xlink:href='{IconSprite}'/></svg>");
}
}
Then used like
<SVGIcon IconSprite="img/icons/symbol-defs.svg#magnifying-glass" />
One thing that I did notice was in order to get the styling to work on the SVG element itself I had to add a separate class to the SVG tag otherwise the styling would not be applied even when using ::deep.

Resize the cursor

I'm building a drawing application (Like paint or Sketchpad) and I need to resize my cursor depending on of the line width of the pencil. The problem is, apparently, you can't resize your cursor. The solution that I found is to use a custom cursor (the normal cursor is changed for an image) and to resize the image. The thing is, I don't know if I need a function to do that or I can directly change the size of the image via SCSS (CSS).
Here's what I've done so far:
private setCursor(cursorType: DrawingCursor): void {
this.Canvas.setAttribute("style", "cursor:url(" + cursorType + "), auto;");}
The cursorType is the url of the custom cursor.
I'm doing this from an angular 8 project (in Typescript).
Thank you !
You can use NgClass binding to implement it. This way the Angular binding takes care of applying the CSS classes so you don't need to set styles manually.
To implement this solution first define the CSS classes for the canvas and the different cursor sizes. For example:
.myCanvas {
width: 400px;
height: 400px;
background-color: green;
}
.brush18px {
cursor: url('brush18px.png'), auto;
}
.brush24px {
cursor: url('brush24px.png'), auto;
}
.brush36px {
cursor: url('brush36px.png'), auto;
}
Then in the component you define a property that will provide the classes for the canvas and a property for the size of the brush. For example:
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
#Input() cursorSize = '18';
get canvasClasses() {
return {
myCanvas: true,
brush18px: this.cursorSize === '18',
brush24px: this.cursorSize === '24',
brush36px: this.cursorSize === '36',
};
};
}
The canvasClasses property must return an object that specifies for each CSS class name if it is applied or not by setting the value to true or false. I use a getter property here so the values update automatically when the size changes.
Now you can bind this in the template and the cursor will automatically update based on the cursorSize value.
Here is how the template looks like:
<canvas [ngClass]="canvasClasses"></canvas>
<br/>
<select [(ngModel)]="cursorSize">
<option>18</option>
<option>24</option>
<option>36</option>
</select>
I have created also a working StackBlitz sample so you can see it in action.
Another possible solution based on the comment on the first answer. This is more of a workaround solution where you hide the actual cursor and move around an image instead so it looks like it is the cursor. This was inspired by the second answer on this post about resizing a cursor image.
I implemented this solution in Angular using a directive that you add to the canvas element in the template. The directive takes as the main parameter the image to show as the cursor and has an additional parameter for the size for the image. I recommend an SVG image that resizes well. Still it is possible to use also a standard image.
Here is the implementation of the Directive for an SVG image:
#Directive({
selector: '[svgCursor]'
})
export class SvgCursorDirective {
private cursorSizeValue: number = 16;
#Input('svgCursor') public svgImage: SVGSVGElement;
#Input() public set cursorSize(cursorSize: number) {
this.cursorSizeValue = cursorSize;
this.updateCursorSize();
}
constructor(el: ElementRef) {
el.nativeElement.style.cursor = 'none'; // hides the browser cursor
}
#HostListener('mouseenter') onMouseEnter() {
// makes image visible only when mous enters the element
this.svgImage.style.visibility = 'visible';
}
#HostListener('mousemove', ['$event']) onMouseMove(e: MouseEvent) {
// draws the image at the mouse position
this.svgImage.style.left = e.clientX.toString();
this.svgImage.style.top = (e.clientY - this.cursorSizeValue).toString();
}
#HostListener('mouseleave') onMouseLeave() {
// hides image when the mouse leaves the element
this.svgImage.style.visibility = 'hidden';
}
private updateCursorSize() {
if (this.svgImage != null) {
this.svgImage.style.width = this.cursorSizeValue.toString();
this.svgImage.style.height = this.cursorSizeValue.toString();
}
}
}
Once you have the directive you can use it in the following way inside a component template:
<svg #cursorImage class="cursor" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M7 14c-1.66 0-3 1.34-3 3 0 1.31-1.16 2-2 2 .92 1.22 2.49 2 4 2 2.21 0 4-1.79 4-4 0-1.66-1.34-3-3-3zm13.71-9.37l-1.34-1.34c-.39-.39-1.02-.39-1.41 0L9 12.25 11.75 15l8.96-8.96c.39-.39.39-1.02 0-1.41z"/></svg>
<canvas class="myCanvas" [svgCursor]="cursorImage" [cursorSize]="cursorSize"></canvas>
As you can see you need to add a template reference variable to the image so you can pass it as a parameter to the svgCursor directive.
Also important for this to work you need to set the correct CSS styles to the image to disable things that are not needed. It is also set to invisble so it becomes visible only when the mouse enters te canvas.
This are the styles I used:
.myCanvas {
width: 400px;
height: 400px;
background-color: lightgreen;
}
.cursor {
position: absolute;
cursor: none;
pointer-events: none;
visibility: hidden;
}
I have created also a working StackBlitz sample so you can see how this works.

Using SVG Icons

I'm using use my own SVG icons and I'm trying to find the best way of using them.
I would like to keep the color but also adjust it if needed to match a theme or on when using hover.
I have tried using the following script which changes the following into an embedded SVG but as I load my scripts at the bottom of my HTML doc, I get a horrible jumping effect.
$(function(){
jQuery('img.svg').each(function(){
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find('svg');
// Add replaced image's ID to the new SVG
if(typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if(typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass+' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Check if the viewport is set, else we gonna set it if we can.
if(!$svg.attr('viewBox') && $svg.attr('height') && $svg.attr('width')) {
$svg.attr('viewBox', '0 0 ' + $svg.attr('height') + ' ' + $svg.attr('width'))
}
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
});
svg {width: 350px; height: 350px;}
svg path {fill: #000 !important;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img src="https://upload.wikimedia.org/wikipedia/commons/f/f8/Windows_logo_-_2012_%28red%29.svg" alt="Microsoft" width="350" />
I've then tried to embed the the SVG by copying the code from Illustrator but the only way I can edit the colours is if I delete them in the html doc as my css won't override them.
What is the best way while keeping them from jumping?
Inline SVGs would be best IMO.
Export your SVGs using Illustrator (if you have troubles, follow this excellent guide by Colin Lord).
Then remove the colors from your SVG code and set them only using CSS.
If you have trouble overriding your colors you can give your SVGs IDs for more specifity.
If you go down the embedded route (which is my preferred option) - you don't actually need the majority of the HTML that Illustrator usually throws out.
Here is an example of your SVG with the most minimal code, then you can just use CSS to change the colours how you wish :-)
svg {
width: 350px;
height: 350px;
}
svg path {
fill: #000;
transform-origin: 0 0;
transform: scale(3)
}
#svg3 path {
fill: turquoise;
}
#svg3:hover path {
fill: green;
}
<svg id="svg2">
<path d="m0,12.402,35.687-4.8602,0.0156,34.423-35.67,0.20313zm35.67,33.529,0.0277,34.453-35.67-4.9041-0.002-29.78zm4.3261-39.025,47.318-6.906,0,41.527-47.318,0.37565zm47.329,39.349-0.0111,41.34-47.318-6.6784-0.0663-34.739z" id="path4"/>
</svg>
<!-- Another exmaple below using CSS to change the colours -->
<svg id="svg3">
<path d="m0,12.402,35.687-4.8602,0.0156,34.423-35.67,0.20313zm35.67,33.529,0.0277,34.453-35.67-4.9041-0.002-29.78zm4.3261-39.025,47.318-6.906,0,41.527-47.318,0.37565zm47.329,39.349-0.0111,41.34-47.318-6.6784-0.0663-34.739z" id="path4"/>
</svg>

Resources