svelte-coordinator
v1.0.0
Published
Library for creating drag coordinators for HTML elements.
Maintainers
Readme
svelte-coordinator
It will help you get the coordinates of the pointer relative to the HTML element to which the main library function is applied.
Applying
There are two ways to use it:
- Using actions and the
use:construction - Using attachments and the
{@attach ...}construction
Using
<script>
import coordinator from 'svelte-coordinator';
const handlers = {};
// Triggered when element is mounted
handlers.init = ({node, box, isTouch}) => {
// Some code
};
// When element unmount
handlers.ondestroy = () => {
// Some code
};
// When cursor or finger tapped in element area
// If this method return false
// Following methods onaction and onend
// Will not respond until the pointer is released
handlers.onstart = (params, event) => {
const {top, left, width, height} = params;
// Some code
};
// When pointer moving in pushed state
handlers.onactions = (params, event) => {
const {top, left, width, height} = params;
// Some code
};
// When pointer is push up
handlers.onend = (params, event) => {
const {top, left, width, height} = params;
// Some code
};
</script>
<div use:coordinator={handlers}></div>
Or you can use new attach sintax
<div {@attach coordinator(handlers)}></div>
<style>
div {
width: 50vw;
height: 50vh;
}
</style>Also
Library have some helpers:
<script>
import {coordinator, clamp, scale} from 'svelte-coordinator';
let x = $state(0);
let y = $state(0);
const handlers = {};
handlers.onaction = ({left, top, width, height}) => {
let xClamp = clamp(left, 0, width);
let yClamp = clamp(top, 0, height);
let xPercent = scale(xClamp, [0, width], [0, 100]) + '%';
let yPercent = scale(yClamp, [0, height], [0, 100]) + '%';
x = xPercent;
y = yPercent;
};
</script>
<div {@attach coordinator(handlers)}>
<span style:top={y} style:left={x}></span>
</div>
<style>
div {
position: relative;
width: 50vw;
height: 50vh;
background-color: #ccc;
}
span {
position: absolute;
width: 10px;
height: 10px;
background-color: red;
transform: translate(-50%, -50%);
}
</style>clamp- Clamps a number within the inclusive range specified by the minimum and maximum valuesvalue- The number to be clampedmin- The lower boundary of the output rangemax- The upper boundary of the output range- return clamped value
scale- Maps a value from one range to another rangevalue- The value to map[inMin, inMax]- The range of the value[outMin, outMax]- The range to map the value to- return mapped value
Example
For example lets create range component:
range.svelte
<script>
import { untrack } from "svelte";
import { coordinator, clamp, scale } from "svelte-coordinator";
let { width = "auto", value = $bindable(0) } = $props();
let x = $state(0);
const handlers = {};
handlers.init = ({ node }) => {
untrack(() => {
let width = node.offsetWidth;
x = scale(clamp(value, 0, 100), [0, 100], [0, width]) + "px";
});
};
handlers.onaction = ({ left, width }) => {
let xPx = clamp(left, 0, width);
x = xPx + "px";
value = Math.round(scale(xPx, [0, width], [0, 100]));
};
</script>
<div
{@attach coordinator(handlers)}
style="--left: {x}; width: {width}"
></div>
<style>
div {
position: relative;
height: 20px;
}
div::before {
content: "";
position: absolute;
top: 50%;
height: 4px;
width: 100%;
border-radius: 2px;
transform: translateY(-50%);
background-color: #989899;
}
div::after {
content: "";
position: absolute;
top: 0;
left: var(--left);
width: var(--size, 20px);
height: var(--size, 20px);
border-radius: 50%;
background-color: white;
transform: translate(-50%);
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
}
</style>app.svelte
<script>
import Progress from './range.svelte'
let value = $state(50);
</script>
Value: {value}
<Progress width="500px" bind:value/>