#html5-canvas #resize #pixi.js
#html5-холст #изменение размера #pixi.js
Вопрос:
Я подготовил полный jsfiddle для моего вопроса —
Для настольной игры я пытаюсь использовать кнопки пользовательского интерфейса jQuery с обеих сторон и назначить остальную часть экрана области рисования Pixi.
Я нашел предложение от Pixi.js разработчику необходимо масштабировать сцену, чтобы ее дочерние элементы масштабировались автоматически, и ниже я пытаюсь это реализовать:
$(function() {
var WIDTH = 400;
var HEIGHT = 400;
var RATIO = WIDTH / HEIGHT;
var scaleX = 1,
scaleY = 1,
offsetX = 0,
offsetY = 0,
oldX, oldY;
var app = new PIXI.Application({
width: WIDTH,
height: HEIGHT,
view: document.getElementById('pixiCanvas'),
backgroundColor: 0xFFFFFF
});
app.stage.interactive = true;
app.stage.on('pointerdown', onDragStart)
.on('pointerup', onDragEnd)
.on('pointerupoutside', onDragEnd)
.on('pointermove', onDragMove);
var background = new PIXI.Graphics();
for (var i = 0; i < 8; i ) {
for (var j = 0; j < 8; j ) {
if ((i j) % 2 == 0) {
background.beginFill(0xCCCCFF);
background.drawRect(i * WIDTH / 8, j * HEIGHT / 8, WIDTH / 8, HEIGHT / 8);
background.endFill();
}
}
}
app.stage.addChild(background);
var bunny = PIXI.Sprite.from('https://pixijs.io/examples/examples/assets/bunny.png');
bunny.anchor.set(0.5);
bunny.scale.set(2);
bunny.x = WIDTH / 2;
bunny.y = HEIGHT / 2;
app.stage.addChild(bunny);
function onDragStart(ev) {
var stagePoint = ev.data.getLocalPosition(app.stage);
if (bunny.getBounds().contains(stagePoint.x, stagePoint.y)) {
bunny.alpha = 0.5;
oldX = stagePoint.x;
oldY = stagePoint.y;
this.data = ev.data;
}
}
function onDragMove() {
if (this.data) {
var stagePoint = this.data.getLocalPosition(app.stage);
bunny.x = stagePoint.x - oldX;
bunny.y = stagePoint.y - oldY;
oldX = stagePoint.x;
oldY = stagePoint.y;
}
}
function onDragEnd() {
if (this.data) {
bunny.alpha = 1;
var stagePoint = this.data.getLocalPosition(app.stage);
this.data = null;
}
}
$(':button').button();
$('#scaleCheck').checkboxradio();
window.onresize = function() {
if (!$('#scaleCheck').prop('checked')) {
return;
}
var canvasRatio = $('#pixiCanvas').width() / $('#pixiCanvas').height();
if (canvasRatio > RATIO) { // if canvas is too wide
scaleX = 1 / canvasRatio;
scaleY = 1;
offsetX = 0;
offsetY = 0;
} else {
scaleX = 1;
scaleY = canvasRatio;
offsetX = 0;
offsetY = 0;
}
app.stage.scale.set(scaleX, scaleY);
app.stage.position.set(offsetX, offsetY); // how to center-align?
}
window.onresize();
});
body {
margin: 0;
padding: 0;
}
#mainDiv {
width: 100%;
height: 100vh;
background: #FFF;
display: flex;
}
#leftMenuDiv {
text-align: center;
background: #FCC;
}
#rightMenuDiv {
text-align: center;
background: #CFC;
flex-shrink: 1;
}
#canvasDiv {
flex-grow: 1;
}
#pixiCanvas {
width: 100%;
height: 100%;
background: #CCF;
box-sizing: border-box;
border: 4px red dotted;
}
<div id="mainDiv">
<div id="leftMenuDiv">
<button id="btn1">Button 1</button><br>
<button id="btn2">Button 2</button><br>
<button id="btn3">Button 3</button><br>
</div>
<div id="canvasDiv">
<canvas id="pixiCanvas"></canvas>
</div>
<div id="rightMenuDiv">
<input id="scaleCheck" type="checkbox">
<label for="scaleCheck">Fit and center Pixi stage</label><br>
<button id="btn4">Button 4</button><br>
<button id="btn5">Button 5</button><br>
<button id="btn6">Button 6</button><br>
</div>
</div>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/pixi.js@5.3.3/dist/pixi.min.js"></script>
Моя проблема с приведенным выше кодом заключается в следующем —
При первом запуске моего кода он работает. Но после того, как вы установите флажок и измените размер окна браузера, перетаскивание прервется.
Ответ №1:
Я смог решить свою проблему с помощью следующего кода:
$(function() {
var WIDTH = 400;
var HEIGHT = 400;
var RATIO = WIDTH / HEIGHT;
var scaleX = 1, scaleY = 1, offsetX = 0, offsetY = 0;
var app = new PIXI.Application({
width: WIDTH,
height: HEIGHT,
view: document.getElementById('pixiCanvas'),
backgroundColor: 0xFFFFFF
});
var background = new PIXI.Graphics();
for (var i = 0; i < 8; i ) {
for (var j = 0; j < 8; j ) {
if ((i j) % 2 == 0) {
background.beginFill(0xCCCCFF);
background.drawRect(i * WIDTH / 8, j * HEIGHT / 8, WIDTH / 8, HEIGHT / 8);
background.endFill();
}
}
}
app.stage.addChild(background);
var bunny = PIXI.Sprite.from('https://pixijs.io/examples/examples/assets/bunny.png');
bunny.interactive = true;
bunny.buttonMode = true;
bunny.anchor.set(0.5);
bunny.scale.set(2);
bunny.x = WIDTH / 2;
bunny.y = HEIGHT / 2;
bunny.on('pointerdown', onDragStart)
.on('pointerup', onDragEnd)
.on('pointerupoutside', onDragEnd)
.on('pointermove', onDragMove);
app.stage.addChild(bunny);
function onDragStart(ev) {
this.data = ev.data;
this.alpha = 0.5;
}
function onDragMove() {
if (this.data) {
var newPos = this.data.getLocalPosition(this.parent);
this.x = newPos.x;
this.y = newPos.y;
}
}
function onDragEnd() {
if (this.data) {
this.alpha = 1;
this.data = null;
}
}
$(':button').button();
$('#scaleCheck').checkboxradio();
window.onresize = function() {
if (!$('#scaleCheck').prop('checked')) {
return;
}
var canvasRatio = $('#pixiCanvas').width() / $('#pixiCanvas').height();
if (canvasRatio > RATIO) { // if canvas is too wide
scaleX = RATIO / canvasRatio;
scaleY = 1;
offsetX = (1 - scaleX) * WIDTH / 2;
offsetY = 0;
} else {
scaleX = 1;
scaleY = canvasRatio / RATIO;
offsetX = 0;
offsetY = (1 - scaleY) * HEIGHT / 2;
}
app.stage.scale.set(scaleX, scaleY);
app.stage.position.set(offsetX, offsetY);
}
window.onresize();
});
body {
margin: 0;
padding: 0;
}
#mainDiv {
width: 100%;
height: 100vh;
background: #FFF;
display: flex;
}
#leftMenuDiv {
text-align: center;
background: #FCC;
}
#rightMenuDiv {
text-align: center;
background: #CFC;
flex-shrink: 1;
}
#canvasDiv {
flex-grow: 1;
}
#pixiCanvas {
width: 100%;
height: 100%;
background: #CCF;
box-sizing: border-box;
border: 4px red dotted;
}
<div id="mainDiv">
<div id="leftMenuDiv">
<button id="btn1">Button 1</button><br>
<button id="btn2">Button 2</button><br>
<button id="btn3">Button 3</button><br>
</div>
<div id="canvasDiv">
<canvas id="pixiCanvas"></canvas>
</div>
<div id="rightMenuDiv">
<input id="scaleCheck" type="checkbox" checked>
<label for="scaleCheck">Fit and center Pixi stage</label><br>
<button id="btn4">Button 4</button><br>
<button id="btn5">Button 5</button><br>
<button id="btn6">Button 6</button><br>
</div>
</div>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/pixi.js@5.3.3/dist/pixi.min.js"></script>
Основным изменением для меня было сделать перетаскиваемый спрайт интерактивным и добавить к нему прослушиватели перетаскивания — вместо app.stage
.
Может app.stage
быть, это может быть интерактивным, а также в моем исходном коде? Я думаю, что в этом случае требуется какое-то матричное вычисление, поэтому математику сложно понять.