physics2.html 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <html>
  2. <head>
  3. <meta charset="UTF-8" />
  4. <title>spine-pixi</title>
  5. <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/pixi.min.js"></script>
  6. <script src="../dist/iife/spine-pixi-v7.js"></script>
  7. <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/tweakpane.min.js"></script>
  8. <link rel="stylesheet" href="../../index.css">
  9. </head>
  10. <body>
  11. <script>
  12. (async function () {
  13. var app = new PIXI.Application({
  14. width: window.innerWidth,
  15. height: window.innerHeight,
  16. resolution: window.devicePixelRatio || 1,
  17. autoDensity: true,
  18. resizeTo: window,
  19. backgroundColor: 0x333333,
  20. hello: true,
  21. });
  22. document.body.appendChild(app.view);
  23. // Pre-load the skeleton data and atlas. You can also load .json skeleton data.
  24. PIXI.Assets.add("girlData", "./assets/celestial-circus-pro.skel");
  25. PIXI.Assets.add("girlAtlas", "./assets/celestial-circus-pma.atlas");
  26. await PIXI.Assets.load(["girlData", "girlAtlas"]);
  27. // Create the spine display object
  28. const girl = spine.Spine.from({skeleton: "girlData", atlas: "girlAtlas",
  29. scale: 0.2,
  30. });
  31. // Center the spine object on screen.
  32. girl.x = window.innerWidth / 2;
  33. girl.y = window.innerHeight / 2 + girl.getBounds().height / 4;
  34. // Set animation "eyeblink-long" on track 0, looped.
  35. girl.state.setAnimation(0, "eyeblink-long", true);
  36. // Add the display object to the stage.
  37. app.stage.addChild(girl);
  38. // Make the stage interactive and register pointer events
  39. app.stage.eventMode = "dynamic";
  40. app.stage.hitArea = app.screen;
  41. let isDragging = false;
  42. let lastX = -1, lastY = -1;
  43. app.stage.on("pointerdown", (e) => {
  44. isDragging = true;
  45. let mousePosition = new spine.Vector2(e.data.global.x, e.data.global.y);
  46. lastX = mousePosition.x;
  47. lastY = mousePosition.y;
  48. });
  49. app.stage.on("pointermove", (e) => {
  50. if (isDragging) {
  51. let mousePosition = new spine.Vector2(e.data.global.x, e.data.global.y);
  52. girl.x += mousePosition.x - lastX;
  53. girl.y += mousePosition.y - lastY;
  54. girl.skeleton.physicsTranslate(mousePosition.x - lastX, mousePosition.y - lastY);
  55. lastX = mousePosition.x;
  56. lastY = mousePosition.y;
  57. }
  58. });
  59. const endDrag = () => (isDragging = false);
  60. app.stage.on("pointerup", endDrag);
  61. app.stage.on("pointerupoutside", endDrag);
  62. document.addEventListener('fullscreenchange', () => {
  63. endDrag();
  64. });
  65. const buttonContainer = new PIXI.Container();
  66. buttonContainer.position.set(0, 0);
  67. const buttonBackground = new PIXI.Graphics();
  68. buttonBackground.beginFill(0x000000); // Button background color
  69. buttonBackground.drawRoundedRect(0, 0, 140, 100, 5); // Button dimensions
  70. buttonBackground.endFill();
  71. buttonContainer.addChild(buttonBackground);
  72. buttonContainer.alpha = 0.7;
  73. const fontStyle = {
  74. fill: 0xdddddd,
  75. fontFamily: 'sans-serif',
  76. fontSize: 16,
  77. };
  78. // Create the text label for the heading
  79. const textHeading = new PIXI.Text("Drag anywhere", fontStyle); // Button text and color
  80. textHeading.position.set(15, 15); // Set the position of the text within the button
  81. buttonContainer.addChild(textHeading);
  82. // Create the text label for the FPS counter
  83. const textFps = new PIXI.Text("0 fps", fontStyle);
  84. textFps.position.set(15, 40);
  85. buttonContainer.addChild(textFps);
  86. // Create the text label for the button toggle fullscreen
  87. const textButton = new PIXI.Text("Fullscreen", fontStyle); // Button text and color
  88. textButton.position.set(15, 65); // Set the position of the text within the button
  89. buttonContainer.addChild(textButton);
  90. // Add the button container to the stage
  91. app.stage.addChild(buttonContainer);
  92. buttonContainer.interactive = true;
  93. buttonContainer.buttonMode = true;
  94. let fsEnabled = false;
  95. buttonContainer.on('pointerdown', () => {
  96. if (fsEnabled) {
  97. document.exitFullscreen();
  98. textButton.text = "Fullscreen";
  99. } else {
  100. app.renderer.view.requestFullscreen();
  101. textButton.text = "Windowed";
  102. }
  103. fsEnabled = !fsEnabled;
  104. });
  105. app.ticker.add(throttle(() => textFps.text = app.ticker.FPS.toFixed(2) + " fps", 250));
  106. })();
  107. const throttle = (func, delay) => {
  108. let lastCall = 0;
  109. return (...args) => {
  110. const now = Date.now();
  111. if (now - lastCall >= delay) {
  112. func.apply(this, args);
  113. lastCall = now;
  114. }
  115. };
  116. }
  117. </script>
  118. </body>
  119. </html>