Nate
The reason for using a short touch is that users can touch it briefly when changing their hairstyle, so we want to compensate for that problem as well.
Here's a code you can easily change.
<html>
<script src="https://bxkrl.com/spine-runtime/spine-webgl/dist/iife/spine-webgl.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
</style>
<body>
<canvas id="canvas_1" style="position: absolute; width: 100%; height: 100%;"></canvas>
<script>
var canvas, context, gl, renderer, input, assetManager, input;
var position = new spine.Vector3();
var coords = new spine.Vector3();
var mouse = new spine.Vector3();
var target = null;
var hoverTargets = [null];
var haircolorr = 1;
var haircolorg = 1;
var haircolorb = 1;
var haircolora = 1;
var json_name, atlas_name, hair_scale;
var skeleton;
var skeletonJson;
var offset = new spine.Vector2();
var bounds = new spine.Vector2();
var oldX, oldY, dragX, dragY;
var dragging = false;
var dragOffset = new spine.Vector2();
var after_startX, after_startY;
var startX, startY, currentX, currentY, startTime, endTime, duration;
var controlBones_woman_hair_2 = [
"woman_hair_2_bone_1", "woman_hair_2_bone_2", "woman_hair_2_bone_3", "woman_hair_2_bone_4", "woman_hair_2_bone_5", "woman_hair_2_bone_6", "woman_hair_2_bone_7", "woman_hair_2_bone_8", "woman_hair_2_bone_9"
];
controlbones = controlBones_woman_hair_2;
class App {
constructor() {
this.skeleton = null;
this.animationState = null;
}
loadAssets(canvas) {
canvas.assetManager.loadText("assets/woman_hair_2.json");
canvas.assetManager.loadTextureAtlas("assets/woman_hair_2.atlas");
}
initialize(canvas) {
let assetManager = canvas.assetManager;
let renderer = canvas.renderer;
var atlas = assetManager.require("assets/woman_hair_2.atlas");
var atlasLoader = new spine.AtlasAttachmentLoader(atlas);
skeletonJson = new spine.SkeletonJson(atlasLoader);
var skeletonData = skeletonJson.readSkeletonData(assetManager.require("assets/woman_hair_2.json"));
this.skeleton = new spine.Skeleton(skeletonData);
new spine.CameraController(canvas.htmlCanvas, canvas.renderer.camera);
skeleton = this.skeleton;
skeleton.setToSetupPose();
skeleton.updateWorldTransform();
skeleton.getBounds(offset, bounds, []);
renderer.camera.position.x = offset.x + bounds.x / 2;
renderer.camera.position.y = offset.y + bounds.y / 2;
renderer.skeletonDebugRenderer.drawPaths = true;
renderer.skeletonDebugRenderer.drawBones = true;
renderer.skeletonDebugRenderer.drawMeshHull = true;
renderer.skeletonDebugRenderer.drawMeshTriangles = true;
var input = new spine.Input(canvas_1);
input.addListener({
down: (x, y) => {
startX = x;
startY = y;
var bestDistance = 10000,
index = 0;
var best;
for (var i = 0; i < controlbones.length; i++) {
hoverTargets[i] = null;
let bone = skeleton.findBone(controlbones[i]);
var position = new spine.Vector2(bone.length, 0);
bone.localToWorld(position);
renderer.camera.screenToWorld(coords.set(x, y, 0), canvas_1.clientWidth, canvas_1.clientHeight);
let distance = Math.sqrt((coords.x - bone.x) * (coords.x - bone.x) + (coords.y - bone.y) * (coords.y - bone.y));
if (distance < bestDistance) {
bestDistance = distance;
best = bone;
index = i;
}
}
if (best) hoverTargets[index] = best;
target = best;
},
up: (x, y) => {
target = null;
dragging = false;
},
dragged: (x, y) => {
currentX = x;
currentY = y;
if (!dragging && (Math.abs(currentX - startX) > 5 || Math.abs(currentY - startY) > 5)) {
dragging = true;
after_startX = x;
after_startY = y;
renderer.camera.screenToWorld(coords.set(after_startX, after_startY, 0), canvas_1.clientWidth, canvas_1.clientHeight);
target.localToWorld(dragOffset.set(0, 0));
dragOffset.x -= coords.x;
dragOffset.y -= coords.y;
}
if (dragging) {
dragged(canvas_1, renderer, target, x, y);
}
}
});
function dragged(canvas_1, renderer, target, x, y) {
if (!target) return;
x = spine.MathUtils.clamp(x, 0, canvas_1.clientWidth);
y = spine.MathUtils.clamp(y, 0, canvas_1.clientHeight);
dragX = x;
dragY = y;
var newX = after_startX + 0.20 * (dragX - after_startX) + dragOffset.x;
var newY = after_startY + 0.20 * (dragY - after_startY) + dragOffset.y;
renderer.camera.screenToWorld(coords.set(newX, newY, 0), canvas_1.clientWidth, canvas_1.clientHeight);
position.set(coords.x, coords.y);
if (target.parent) target.parent.worldToLocal(position);
target.x = position.x;
target.y = position.y;
}
}
update(canvas, delta) {
this.skeleton.updateWorldTransform();
}
render(canvas) {
let renderer = canvas.renderer;
renderer.camera.viewportWidth = bounds.x * 1.2;
renderer.camera.viewportHeight = bounds.y * 1.2;
renderer.resize(spine.ResizeMode.Fit);
canvas.clear(0, 0, 0, 0);
// renderer.drawSkeleton(skeleton, true);
renderer.drawSkeletonDebug(skeleton);
skeleton.color = {
r: haircolorr,
g: haircolorg,
b: haircolorb,
a: haircolora
};
renderer.begin();
renderer.drawSkeleton(this.skeleton, true);
// Draw a circle with a radius of 20 pixels around each draggable bone
renderer.end();
}
}
new spine.SpineCanvas(document.getElementById("canvas_1"), {
app: new App()
})
</script>
</body>
</html>
The same problem is still present here.
We will upload the spine assets file together below.