<div class="stage">
<i class="target" id="raw"></i>
<span class="label">Raw value</span>
</div>
<div class="stage">
<i class="target" id="interpolated"></i>
<span class="label">Interpolated value</span>
</div>
body {
background-color: rgb(2, 62, 80);
display: flex;
min-height: 100vh;
align-items: center;
justify-content: center;
font-family: monospace;
color: #fff;
font-size: 14px;
}
.stage {
width: 40vw;
height: 40vw;
border: 1px solid #fff;
margin: 1vw;
position: relative;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10'%3E%3Cpath d='M0 0v10h10' stroke='rgba(255,255,255,0.15)' fill='none'/%3E%3C/svg%3E");
}
.target {
width: 5%;
height: 5%;
background: #fff;
position: absolute;
top: 0;
left: 0;
transform: translate(-50%, -50%);
border-radius: 50%;
transition-property: top, left;
transition-duration: 200ms;
transition-timing-function: ease-out;
}
.label {
position: absolute;
bottom: calc(100% + 0.5vw);
left: 0;
right: 0;
text-align: center;
}
interface Coordinates {
lat: number;
lng: number;
};
const interpolateCoordinates = (interpolation: number = 0.5): {
get: () => Coordinates | null;
set: (newValue: Coordinates) => Coordinates;
} => {
// Initial states
let lastValue: Coordinates | null = null;
let currentValue: Coordinates | null = null;
/**
* Gets the interpolated coordinates between the last and current values
*/
const get = (): Coordinates | null => {
if (!lastValue || !currentValue) return null;
// Calculate difference in stored values
const latDiff = (currentValue.lat - lastValue.lat);
const lngDiff = (currentValue.lng - lastValue.lng);
// Calculate interpolated values
return {
lat: lastValue.lat + (latDiff * interpolation),
lng: lastValue.lng + (lngDiff * interpolation),
};
};
/**
* Stores the current interpolation as the last value and updates the current value
*/
const set = (newValue: Coordinates): Coordinates => {
// Update last value with current interpolated value if available
const interpolatedValue = get() ?? newValue;
lastValue = {...interpolatedValue};
// Update current value
currentValue = {...newValue};
// Return new interpolated value
return get();
};
return {
get,
set,
};
};
// Demo
const coordinates = interpolateCoordinates(0.1);
const targetRaw = document.getElementById('raw');
const targetInterpolated = document.getElementById('interpolated');
setInterval(() => {
// Generate random coordinates
const newCoordinates: Coordinates = {
lat: Math.random() * 100,
lng: Math.random() * 100,
};
// Use raw new coordinates
targetRaw.style.top = `${newCoordinates.lat}%`;
targetRaw.style.left = `${newCoordinates.lng}%`;
// Interpolate coordinates
const interpolated = coordinates.set(newCoordinates);
targetInterpolated.style.top = `${interpolated.lat}%`;
targetInterpolated.style.left = `${interpolated.lng}%`;
}, 200);
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.