Added hover functionality
This commit is contained in:
19
README.md
19
README.md
@@ -5,7 +5,7 @@ A lightweight ES module for creating animated hamburger menu icons that can morp
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Smooth Animations**: 500ms morphing animations between shapes
|
- **Smooth Animations**: 500ms morphing animations between shapes
|
||||||
- **Configurable**: Customize size and color
|
- **Configurable**: Customize size, foreground, background, and hover colors
|
||||||
- **Lightweight**: Minimal dependencies (only SVG.js)
|
- **Lightweight**: Minimal dependencies (only SVG.js)
|
||||||
- **ES Module**: Modern JavaScript module format
|
- **ES Module**: Modern JavaScript module format
|
||||||
- **Multiple Shapes**: Support for 8 different icon shapes
|
- **Multiple Shapes**: Support for 8 different icon shapes
|
||||||
@@ -43,7 +43,9 @@ git submodule add <repository-url> lib/hamburger-morphing
|
|||||||
// Create hamburger instance
|
// Create hamburger instance
|
||||||
const hamburger = new HamburgerMorphing('#menu-icon', {
|
const hamburger = new HamburgerMorphing('#menu-icon', {
|
||||||
size: 80,
|
size: 80,
|
||||||
color: '#ff6b6b'
|
foreground: '#ff6b6b',
|
||||||
|
background: '#ffffff',
|
||||||
|
hover: '#ff0000'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Morph to different shapes
|
// Morph to different shapes
|
||||||
@@ -66,13 +68,16 @@ new HamburgerMorphing(containerSelector, options)
|
|||||||
- `containerSelector` (string): CSS selector for the container element
|
- `containerSelector` (string): CSS selector for the container element
|
||||||
- `options` (object, optional): Configuration options
|
- `options` (object, optional): Configuration options
|
||||||
- `size` (number, default: 100): Size of the SVG in pixels
|
- `size` (number, default: 100): Size of the SVG in pixels
|
||||||
- `color` (string, default: "#000"): Stroke color for the lines
|
- `foreground` (string, default: "#000000"): Foreground/stroke color for the lines
|
||||||
|
- `background` (string, default: "#ffffff"): Background color for cutout effects
|
||||||
|
- `hover` (string, default: "#ff0000"): Hover color for interactive effects
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
```javascript
|
```javascript
|
||||||
const hamburger = new HamburgerMorphing('#menu', {
|
const hamburger = new HamburgerMorphing('#menu', {
|
||||||
size: 60,
|
size: 60,
|
||||||
color: '#333'
|
foreground: '#333333',
|
||||||
|
background: '#ffffff'
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -102,6 +107,9 @@ Animates the hamburger icon to the specified shape.
|
|||||||
- `'carrot_left'` - Carrot/play shape pointing left
|
- `'carrot_left'` - Carrot/play shape pointing left
|
||||||
- `'carrot_up'` - Carrot/play shape pointing up
|
- `'carrot_up'` - Carrot/play shape pointing up
|
||||||
- `'carrot_down'` - Carrot/play shape pointing down
|
- `'carrot_down'` - Carrot/play shape pointing down
|
||||||
|
- `'circle'` - Perfect circle shape
|
||||||
|
- `'doughnut'` - Doughnut shape with center cutout
|
||||||
|
- `'moon'` - Crescent moon shape
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
```javascript
|
```javascript
|
||||||
@@ -170,6 +178,9 @@ hamburger.destroy();
|
|||||||
<button onclick="changeShape('carrot_left')">Carrot Left</button>
|
<button onclick="changeShape('carrot_left')">Carrot Left</button>
|
||||||
<button onclick="changeShape('carrot_up')">Carrot Up</button>
|
<button onclick="changeShape('carrot_up')">Carrot Up</button>
|
||||||
<button onclick="changeShape('carrot_down')">Carrot Down</button>
|
<button onclick="changeShape('carrot_down')">Carrot Down</button>
|
||||||
|
<button onclick="changeShape('circle')">Circle</button>
|
||||||
|
<button onclick="changeShape('doughnut')">Doughnut</button>
|
||||||
|
<button onclick="changeShape('moon')">Moon</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-color: #f0f0f0;
|
|
||||||
}
|
}
|
||||||
#divSvgOut {
|
#divSvgOut {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -70,6 +70,9 @@
|
|||||||
<button onclick="animateTo('carrot_left')">Carrot Left</button>
|
<button onclick="animateTo('carrot_left')">Carrot Left</button>
|
||||||
<button onclick="animateTo('carrot_up')">Carrot Up</button>
|
<button onclick="animateTo('carrot_up')">Carrot Up</button>
|
||||||
<button onclick="animateTo('carrot_down')">Carrot Down</button>
|
<button onclick="animateTo('carrot_down')">Carrot Down</button>
|
||||||
|
<button onclick="animateTo('circle')">Circle</button>
|
||||||
|
<button onclick="animateTo('doughnut')">Doughnut</button>
|
||||||
|
<button onclick="animateTo('moon')">Moon</button>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 20px; padding: 10px; border: 1px solid #ccc; background-color: #f9f9f9; width: 400px; height: 200px; overflow: auto;">
|
<div style="margin-top: 20px; padding: 10px; border: 1px solid #ccc; background-color: #f9f9f9; width: 400px; height: 200px; overflow: auto;">
|
||||||
<textarea id="svgCode" style="font-size: 12px; width: 100%; height: 150px; margin: 0; font-family: monospace;"></textarea>
|
<textarea id="svgCode" style="font-size: 12px; width: 100%; height: 150px; margin: 0; font-family: monospace;"></textarea>
|
||||||
|
|||||||
173
hamburger.mjs
173
hamburger.mjs
@@ -7,13 +7,20 @@
|
|||||||
const STROKE_WIDTH = 29;
|
const STROKE_WIDTH = 29;
|
||||||
const ANIMATION_DURATION = 500;
|
const ANIMATION_DURATION = 500;
|
||||||
|
|
||||||
|
// Default colors for light and dark mode compatibility
|
||||||
|
const DEFAULT_FOREGROUND = "#000000";
|
||||||
|
const DEFAULT_BACKGROUND = "#ffffff";
|
||||||
|
const DEFAULT_HOVER = "#ff0000";
|
||||||
|
|
||||||
export class HamburgerMorphing {
|
export class HamburgerMorphing {
|
||||||
/**
|
/**
|
||||||
* Creates a new hamburger morphing animation instance
|
* Creates a new hamburger morphing animation instance
|
||||||
* @param {string} containerSelector - CSS selector for the container element
|
* @param {string} containerSelector - CSS selector for the container element
|
||||||
* @param {Object} options - Configuration options
|
* @param {Object} options - Configuration options
|
||||||
* @param {number} [options.size=100] - Size of the SVG in pixels
|
* @param {number} [options.size=100] - Size of the SVG in pixels
|
||||||
* @param {string} [options.color="#000"] - Stroke color for the lines
|
* @param {string} [options.foreground="#000000"] - Foreground/stroke color for the lines
|
||||||
|
* @param {string} [options.background="#ffffff"] - Background color for cutout effects
|
||||||
|
* @param {string} [options.hover="#ff0000"] - Hover color for interactive effects
|
||||||
*/
|
*/
|
||||||
constructor(containerSelector, options = {}) {
|
constructor(containerSelector, options = {}) {
|
||||||
this.container = document.querySelector(containerSelector);
|
this.container = document.querySelector(containerSelector);
|
||||||
@@ -23,7 +30,9 @@ export class HamburgerMorphing {
|
|||||||
|
|
||||||
this.options = {
|
this.options = {
|
||||||
size: options.size || 100,
|
size: options.size || 100,
|
||||||
color: options.color || "#000"
|
foreground: options.foreground || DEFAULT_FOREGROUND,
|
||||||
|
background: options.background || DEFAULT_BACKGROUND,
|
||||||
|
hover: options.hover || DEFAULT_HOVER
|
||||||
};
|
};
|
||||||
|
|
||||||
this.draw = null;
|
this.draw = null;
|
||||||
@@ -32,13 +41,17 @@ export class HamburgerMorphing {
|
|||||||
this.line3 = null;
|
this.line3 = null;
|
||||||
|
|
||||||
this.stroke = {
|
this.stroke = {
|
||||||
color: this.options.color,
|
color: this.options.foreground,
|
||||||
width: STROKE_WIDTH,
|
width: STROKE_WIDTH,
|
||||||
linecap: "round",
|
linecap: "round",
|
||||||
linejoin: "round",
|
linejoin: "round",
|
||||||
};
|
};
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
|
|
||||||
|
// Add hover event listeners
|
||||||
|
this.container.addEventListener('mouseenter', () => this.onHover(true));
|
||||||
|
this.container.addEventListener('mouseleave', () => this.onHover(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,9 +65,9 @@ export class HamburgerMorphing {
|
|||||||
this.draw = SVG().addTo(this.container).size('100%', '100%').viewbox(0, 0, 100, 100);
|
this.draw = SVG().addTo(this.container).size('100%', '100%').viewbox(0, 0, 100, 100);
|
||||||
|
|
||||||
// Create the three lines
|
// Create the three lines
|
||||||
this.line1 = this.draw.line(20, 20, 80, 20).fill("#fff").stroke(this.stroke);
|
this.line1 = this.draw.line(20, 20, 80, 20).fill(this.options.background).stroke(this.stroke);
|
||||||
this.line2 = this.draw.line(20, 50, 80, 50).fill("#fff").stroke(this.stroke);
|
this.line2 = this.draw.line(20, 50, 80, 50).fill(this.options.background).stroke(this.stroke);
|
||||||
this.line3 = this.draw.line(20, 80, 80, 80).fill("#fff").stroke(this.stroke);
|
this.line3 = this.draw.line(20, 80, 80, 80).fill(this.options.background).stroke(this.stroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,103 +79,123 @@ export class HamburgerMorphing {
|
|||||||
throw new Error('HamburgerMorphing not properly initialized');
|
throw new Error('HamburgerMorphing not properly initialized');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
switch (shape) {
|
switch (shape) {
|
||||||
case 'x':
|
case 'x':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 20, y2: 80 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 20, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 80, y2: 20 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 80, y2: 20, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 80, y2: 20 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 80, y2: 20, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'plus':
|
case 'plus':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 50 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 20, y2: 80 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 20, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'minus':
|
case 'minus':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 50 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'burger':
|
case 'burger':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 20, y2: 20 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 20, y2: 20, opacity: 1, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 50 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 50, opacity: 1, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 80, y2: 80 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 80, y2: 80, opacity: 1, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'arrow_left':
|
case 'arrow_left':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 20, y1: 20, y2: 50 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 20, y1: 20, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 65, x2: 80, y1: 50, y2: 50 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 65, x2: 80, y1: 50, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 20, y1: 80, y2: 50 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 20, y1: 80, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'arrow_down':
|
case 'arrow_down':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 50, y2: 80 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 50, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 20, y2: 35 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 20, y2: 35, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 50, y1: 50, y2: 80 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 50, y1: 50, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'arrow_up':
|
case 'arrow_up':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 50, y2: 20 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 50, y2: 20, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 80, y2: 65 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 80, y2: 65, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 50, y1: 50, y2: 20 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 50, y1: 50, y2: 20, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'arrow_right':
|
case 'arrow_right':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 20, y2: 50 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 20, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 35, y1: 50, y2: 50 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 35, y1: 50, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 80, y2: 50 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 80, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'triangle_up':
|
case 'triangle_up':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 80, y2: 20 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 80, y2: 20, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 20, y2: 80 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 20, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 80, y2: 80 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 80, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'triangle_down':
|
case 'triangle_down':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 20, y2: 80 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 20, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 80, y2: 20 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 80, y2: 20, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 20, y2: 20 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 20, y2: 20, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'triangle_left':
|
case 'triangle_left':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 20, y2: 50 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 20, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 80 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 80, y1: 20, y2: 80 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 80, y1: 20, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'triangle_right':
|
case 'triangle_right':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 20, y2: 50 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 20, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 50, y2: 80 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 50, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 20, y1: 20, y2: 80 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 20, y1: 20, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'carrot_right':
|
case 'carrot_right':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 20, y2: 50 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 20, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 50, y2: 80 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 50, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 50, y2: 80 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 50, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'carrot_left':
|
case 'carrot_left':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 20, y2: 50 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 80, x2: 20, y1: 20, y2: 50, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 80 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 80 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 80, y1: 50, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'carrot_up':
|
case 'carrot_up':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 80, y2: 20 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 80, y2: 20, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 20, y2: 80 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 20, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 20, y2: 80 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 20, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'carrot_down':
|
case 'carrot_down':
|
||||||
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 20, y2: 80 });
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 20, x2: 50, y1: 20, y2: 80, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 80, y2: 20 });
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 80, y2: 20, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 80, y2: 20 });
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 80, y1: 80, y2: 20, 'stroke-width': STROKE_WIDTH, stroke: this.options.foreground });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'circle':
|
||||||
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50, 'stroke-width': 90 , stroke: this.options.foreground });
|
||||||
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50, 'stroke-width': 90 , stroke: this.options.foreground });
|
||||||
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50, 'stroke-width': 90 , stroke: this.options.foreground });
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'doughnut':
|
||||||
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50, 'stroke-width': 90 });
|
||||||
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50, 'stroke-width': 90 });
|
||||||
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 50, x2: 50, y1: 50, y2: 50, 'stroke-width': 45, stroke: this.options.background });
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'moon':
|
||||||
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 60, x2: 60, y1: 50, y2: 50, 'stroke-width': 90 });
|
||||||
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 60, x2: 60, y1: 50, y2: 50, 'stroke-width': 90 });
|
||||||
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ x1: 90, x2: 90, y1: 50, y2: 50, 'stroke-width': 90, stroke: this.options.background });
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unknown shape: ${shape}`);
|
throw new Error(`Unknown shape: ${shape}`);
|
||||||
}
|
}
|
||||||
@@ -184,23 +217,49 @@ export class HamburgerMorphing {
|
|||||||
const y1 = Math.round(line.getAttribute('y1'));
|
const y1 = Math.round(line.getAttribute('y1'));
|
||||||
const x2 = Math.round(line.getAttribute('x2'));
|
const x2 = Math.round(line.getAttribute('x2'));
|
||||||
const y2 = Math.round(line.getAttribute('y2'));
|
const y2 = Math.round(line.getAttribute('y2'));
|
||||||
const stroke = line.getAttribute('stroke') || this.options.color;
|
const stroke = line.getAttribute('stroke') || this.options.foreground;
|
||||||
const strokeWidth = line.getAttribute('stroke-width') || '38';
|
const strokeWidth = line.getAttribute('stroke-width') || STROKE_WIDTH.toString();
|
||||||
const strokeLinecap = line.getAttribute('stroke-linecap') || 'round';
|
const strokeLinecap = line.getAttribute('stroke-linecap') || 'round';
|
||||||
const strokeLinejoin = line.getAttribute('stroke-linejoin') || 'round';
|
const strokeLinejoin = line.getAttribute('stroke-linejoin') || 'round';
|
||||||
const fill = line.getAttribute('fill') || '#fff';
|
const fill = line.getAttribute('fill') || '#fff';
|
||||||
|
const opacity = line.getAttribute('opacity') || '1';
|
||||||
|
|
||||||
svgCode += ` <line x1="${x1}" x2="${x2}" y1="${y1}" y2="${y2}" stroke="${stroke}" stroke-width="${strokeWidth}" stroke-linecap="${strokeLinecap}" stroke-linejoin="${strokeLinejoin}" fill="${fill}"></line>\n`;
|
svgCode += ` <line x1="${x1}" x2="${x2}" y1="${y1}" y2="${y2}" stroke="${stroke}" stroke-width="${strokeWidth}" stroke-linecap="${strokeLinecap}" stroke-linejoin="${strokeLinejoin}" fill="${fill}" opacity="${opacity}"></line>\n`;
|
||||||
});
|
});
|
||||||
|
|
||||||
svgCode += `</svg>`;
|
svgCode += `</svg>`;
|
||||||
return svgCode;
|
return svgCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles hover state changes with animation
|
||||||
|
* @param {boolean} isHovering - Whether the mouse is hovering
|
||||||
|
*/
|
||||||
|
onHover(isHovering) {
|
||||||
|
if (!this.line1 || !this.line2 || !this.line3) return;
|
||||||
|
|
||||||
|
const targetColor = isHovering ? this.options.hover : this.options.foreground;
|
||||||
|
|
||||||
|
// Only change color for lines that have the foreground color (not background/cutout colors)
|
||||||
|
if (this.line1.attr('stroke') === this.options.foreground || this.line1.attr('stroke') === this.options.hover) {
|
||||||
|
this.line1.animate(ANIMATION_DURATION, 0, "now").attr({ stroke: targetColor });
|
||||||
|
}
|
||||||
|
if (this.line2.attr('stroke') === this.options.foreground || this.line2.attr('stroke') === this.options.hover) {
|
||||||
|
this.line2.animate(ANIMATION_DURATION, 0, "now").attr({ stroke: targetColor });
|
||||||
|
}
|
||||||
|
if (this.line3.attr('stroke') === this.options.foreground || this.line3.attr('stroke') === this.options.hover) {
|
||||||
|
this.line3.animate(ANIMATION_DURATION, 0, "now").attr({ stroke: targetColor });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the hamburger morphing instance and cleans up the DOM
|
* Destroys the hamburger morphing instance and cleans up the DOM
|
||||||
*/
|
*/
|
||||||
destroy() {
|
destroy() {
|
||||||
|
// Remove event listeners
|
||||||
|
this.container.removeEventListener('mouseenter', () => this.onHover(true));
|
||||||
|
this.container.removeEventListener('mouseleave', () => this.onHover(false));
|
||||||
|
|
||||||
if (this.draw) {
|
if (this.draw) {
|
||||||
this.draw.remove();
|
this.draw.remove();
|
||||||
this.draw = null;
|
this.draw = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user