我正在我的reactjs应用程序https://konvajs.github.io/docs/sandbox/Wheel_of_Fortune.html
中实现这种“幸运之轮”这是组件的代码:
import React from "react";
import { Link } from "react-router-dom";
class RollTabak extends React.Component {
constructor() {
super();
var width = window.innerWidth;
var height = window.innerHeight;
Konva.angleDeg = false;
var angularVelocity = 6;
var angularVelocities = [];
var lastRotation = 0;
var controlled = false;
var numWedges = 25;
var angularFriction = 0.2;
var target, activeWedge, stage, layer, wheel, pointer;
var finished = false;
}
render() {
return (
<div>
<div id="container"></div>
</div>
);
}
componentDidMount(){
this.init();
}
getAverageAngularVelocity() {
var total = 0;
var len = this.angularVelocities.length;
if (len === 0) {
return 0;
}
for (var n = 0; n < len; n++) {
total += this.angularVelocities[n];
}
return total / len;
}
purifyColor(color) {
var randIndex = Math.round(Math.random() * 3);
color[randIndex] = 0;
return color;
}
getRandomColor() {
var r = 100 + Math.round(Math.random() * 55);
var g = 100 + Math.round(Math.random() * 55);
var b = 100 + Math.round(Math.random() * 55);
var color = [r, g, b];
color = purifyColor(color);
color = purifyColor(color);
return color;
}
bind() {
this.wheel.on('mousedown', function (evt) {
this.angularVelocity = 0;
this.controlled = true;
this.target = evt.target;
this.finished = false;
});
// add listeners to container
document.body.addEventListener('mouseup', function () {
this.controlled = false;
this.angularVelocity = getAverageAngularVelocity() * 5;
if (this.angularVelocity > 20) {
this.angularVelocity = 20;
}
else if (this.angularVelocity < -20) {
this.angularVelocity = -20;
}
this.angularVelocities = [];
}, false);
document.body.addEventListener('mousemove', function (evt) {
var mousePos = this.stage.getPointerPosition();
if (this.controlled && this.mousePos && this.target) {
var x = this.mousePos.x - this.wheel.getX();
var y = this.mousePos.y - this.wheel.getY();
var atan = Math.atan(y / x);
var rotation = x >= 0 ? atan : atan + Math.PI;
var targetGroup = this.target.getParent();
this.wheel.setRotation(this.rotation - targetGroup.startRotation - (this.target.getAngle() / 2));
}
}, false);
}
getRandomReward() {
var mainDigit = Math.round(Math.random() * 9);
return mainDigit + '\n0\n0';
}
addWedge(n) {
var s = getRandomColor();
var reward = getRandomReward();
var r = s[0];
var g = s[1];
var b = s[2];
var angle = 2 * Math.PI / this.numWedges;
var endColor = 'rgb(' + r + ',' + g + ',' + b + ')';
r += 100;
g += 100;
b += 100;
var startColor = 'rgb(' + r + ',' + g + ',' + b + ')';
var wedge = new Konva.Group({
rotation: 2 * n * Math.PI / this.numWedges,
});
var wedgeBackground = new Konva.Wedge({
radius: 400,
angle: angle,
fillRadialGradientStartPoint: 0,
fillRadialGradientStartRadius: 0,
fillRadialGradientEndPoint: 0,
fillRadialGradientEndRadius: 400,
fillRadialGradientColorStops: [0, startColor, 1, endColor],
fill: '#64e9f8',
fillPriority: 'radial-gradient',
stroke: '#ccc',
strokeWidth: 2
});
wedge.add(wedgeBackground);
var text = new Konva.Text({
text: reward,
fontFamily: 'Calibri',
fontSize: 50,
fill: 'white',
align: 'center',
stroke: 'yellow',
strokeWidth: 1,
rotation: (Math.PI + angle) / 2,
x: 380,
y: 30,
listening: false
});
wedge.add(text);
text.cache();
wedge.startRotation = wedge.getRotation();
this.wheel.add(wedge);
}
animate(frame) {
// handle wheel spin
var angularVelocityChange = this.angularVelocity * this.frame.timeDiff * (1 - this.angularFriction) / 1000;
this.angularVelocity -= this.angularVelocityChange;
// activate / deactivate wedges based on point intersection
var shape = this.stage.getIntersection({
x: this.stage.getWidth() / 2,
y: 100
});
if (this.controlled) {
if (this.angularVelocities.length > 10) {
this.angularVelocities.shift();
}
this.angularVelocities.push((this.wheel.getRotation() - this.lastRotation) * 1000 / this.frame.timeDiff);
}
else {
var diff = this.frame.timeDiff * this.angularVelocity / 1000;
if (diff > 0.0001) {
this.wheel.rotate(diff);
} else if (!this.finished && !this.controlled) {
if (this.shape) {
var text = this.shape.getParent().findOne('Text').text();
var price = text.split('\n').join('');
alert('You price is ' + price);
}
this.finished = true;
}
}
lastRotation = this.wheel.getRotation();
if (this.shape) {
if (this.shape && (!this.activeWedge || (this.shape._id !== this.activeWedge._id))) {
this.pointer.setY(20);
new Konva.Tween({
node: pointer,
duration: 0.3,
y: 30,
easing: Konva.Easings.ElasticEaseOut
}).play();
if (this.activeWedge) {
this.activeWedge.setFillPriority('radial-gradient');
}
this.shape.setFillPriority('fill');
this.activeWedge = this.shape;
}
}
}
init() {
this.stage = new Konva.Stage({
container: 'container',
width: this.width,
height: this.height
});
this.layer = new Konva.Layer();
this.wheel = new Konva.Group({
x: this.stage.getWidth() / 2,
y: 410
});
for (var n = 0; n < this.numWedges; n++) {
addWedge(n);
}
this.pointer = new Konva.Wedge({
fillRadialGradientStartPoint: 0,
fillRadialGradientStartRadius: 0,
fillRadialGradientEndPoint: 0,
fillRadialGradientEndRadius: 30,
fillRadialGradientColorStops: [0, 'white', 1, 'red'],
stroke: 'white',
strokeWidth: 2,
lineJoin: 'round',
angle: 1,
radius: 30,
x: this.stage.getWidth() / 2,
y: 33,
rotation: -90,
shadowColor: 'black',
shadowOffset: 3,
shadowBlur: 2,
shadowOpacity: 0.5
});
// add components to the stage
this.layer.add(this.wheel);
this.layer.add(this.pointer);
this.stage.add(this.layer);
// bind events
this.bind();
var anim = new Konva.Animation(this.animate, this.layer);
// wait one second and then spin the wheel
setTimeout(function () {
anim.start();
}, 1000);
}
}
export default RollTabak;
控制台中的错误是:
RollTabak.js?763e:87 Uncaught TypeError: Cannot read property 'getPointerPosition' of undefined
at HTMLBodyElement.eval (RollTabak.js?763e:87)
我可以弄清楚this.stage
是未定义的,但我不知道为什么。
我对Reactjs很陌生,如果有经验的人可以给我一些建议来解决这个问题,那将是很好的。
答案 0 :(得分:0)
我猜想事件监听器即使在组件卸载后仍会运行-导致this.stage未定义。您必须在卸载事件上删除事件侦听器:
componentWillUnmount() {
document.body.removeEventListener('yourEvent', yourFunction);
}
答案 1 :(得分:0)
this
上下文在代码中的多个位置存在问题。我已经将它们固定在某些地方,因此没有未定义的消息。例如
this.animate.bind(this)
,您需要在调用animate函数时绑定此上下文,还需要在事件侦听器回调中使用箭头函数,以便将this
上下文保留在内部。您是否应该了解一下为什么您的代码无法正常工作。
class RollTabak extends React.Component {
constructor() {
super();
var width = window.innerWidth;
var height = window.innerHeight;
Konva.angleDeg = false;
var angularVelocity = 6;
var angularVelocities = [];
var lastRotation = 0;
var controlled = false;
var numWedges = 25;
var angularFriction = 0.2;
var target, activeWedge, stage, layer, wheel, pointer;
var finished = false;
}
render() {
return (
<div>
<div id="container"></div>
</div>
);
}
componentDidMount(){
this.init();
}
getAverageAngularVelocity() {
var total = 0;
var len = this.angularVelocities.length;
if (len === 0) {
return 0;
}
for (var n = 0; n < len; n++) {
total += this.angularVelocities[n];
}
return total / len;
}
purifyColor(color) {
var randIndex = Math.round(Math.random() * 3);
color[randIndex] = 0;
return color;
}
getRandomColor() {
var r = 100 + Math.round(Math.random() * 55);
var g = 100 + Math.round(Math.random() * 55);
var b = 100 + Math.round(Math.random() * 55);
var color = [r, g, b];
color = purifyColor(color);
color = purifyColor(color);
return color;
}
bind() {
this.wheel.on('mousedown', evt => {
this.angularVelocity = 0;
this.controlled = true;
this.target = evt.target;
this.finished = false;
});
// add listeners to container
document.body.addEventListener('mouseup', () => {
this.controlled = false;
this.angularVelocity = getAverageAngularVelocity() * 5;
if (this.angularVelocity > 20) {
this.angularVelocity = 20;
}
else if (this.angularVelocity < -20) {
this.angularVelocity = -20;
}
this.angularVelocities = [];
}, false);
document.body.addEventListener('mousemove', evt => {
var mousePos = this.stage.getPointerPosition();
if (this.controlled && this.mousePos && this.target) {
var x = this.mousePos.x - this.wheel.getX();
var y = this.mousePos.y - this.wheel.getY();
var atan = Math.atan(y / x);
var rotation = x >= 0 ? atan : atan + Math.PI;
var targetGroup = this.target.getParent();
this.wheel.setRotation(this.rotation - targetGroup.startRotation - (this.target.getAngle() / 2));
}
}, false);
}
getRandomReward() {
var mainDigit = Math.round(Math.random() * 9);
return mainDigit + '\n0\n0';
}
addWedge(n) {
var s = getRandomColor();
var reward = getRandomReward();
var r = s[0];
var g = s[1];
var b = s[2];
var angle = 2 * Math.PI / this.numWedges;
var endColor = 'rgb(' + r + ',' + g + ',' + b + ')';
r += 100;
g += 100;
b += 100;
var startColor = 'rgb(' + r + ',' + g + ',' + b + ')';
var wedge = new Konva.Group({
rotation: 2 * n * Math.PI / this.numWedges,
});
var wedgeBackground = new Konva.Wedge({
radius: 400,
angle: angle,
fillRadialGradientStartPoint: 0,
fillRadialGradientStartRadius: 0,
fillRadialGradientEndPoint: 0,
fillRadialGradientEndRadius: 400,
fillRadialGradientColorStops: [0, startColor, 1, endColor],
fill: '#64e9f8',
fillPriority: 'radial-gradient',
stroke: '#ccc',
strokeWidth: 2
});
wedge.add(wedgeBackground);
var text = new Konva.Text({
text: reward,
fontFamily: 'Calibri',
fontSize: 50,
fill: 'white',
align: 'center',
stroke: 'yellow',
strokeWidth: 1,
rotation: (Math.PI + angle) / 2,
x: 380,
y: 30,
listening: false
});
wedge.add(text);
text.cache();
wedge.startRotation = wedge.getRotation();
this.wheel.add(wedge);
}
animate(frame) {
// handle wheel spin
var angularVelocityChange = this.angularVelocity * frame.timeDiff * (1 - this.angularFriction) / 1000;
this.angularVelocity -= this.angularVelocityChange;
// activate / deactivate wedges based on point intersection
var shape = this.stage.getIntersection({
x: this.stage.getWidth() / 2,
y: 100
});
if (this.controlled) {
if (this.angularVelocities.length > 10) {
this.angularVelocities.shift();
}
this.angularVelocities.push((this.wheel.getRotation() - this.lastRotation) * 1000 / frame.timeDiff);
}
else {
var diff = frame.timeDiff * this.angularVelocity / 1000;
if (diff > 0.0001) {
this.wheel.rotate(diff);
} else if (!this.finished && !this.controlled) {
if (this.shape) {
var text = this.shape.getParent().findOne('Text').text();
var price = text.split('\n').join('');
alert('You price is ' + price);
}
this.finished = true;
}
}
this.lastRotation = this.wheel.getRotation();
if (this.shape) {
if (this.shape && (!this.activeWedge || (this.shape._id !== this.activeWedge._id))) {
this.pointer.setY(20);
new Konva.Tween({
node: pointer,
duration: 0.3,
y: 30,
easing: Konva.Easings.ElasticEaseOut
}).play();
if (this.activeWedge) {
this.activeWedge.setFillPriority('radial-gradient');
}
this.shape.setFillPriority('fill');
this.activeWedge = this.shape;
}
}
}
init() {
this.stage = new Konva.Stage({
container: 'container',
width: this.width,
height: this.height
});
this.layer = new Konva.Layer();
this.wheel = new Konva.Group({
x: this.stage.getWidth() / 2,
y: 410
});
for (var n = 0; n < this.numWedges; n++) {
addWedge(n);
}
this.pointer = new Konva.Wedge({
fillRadialGradientStartPoint: 0,
fillRadialGradientStartRadius: 0,
fillRadialGradientEndPoint: 0,
fillRadialGradientEndRadius: 30,
fillRadialGradientColorStops: [0, 'white', 1, 'red'],
stroke: 'white',
strokeWidth: 2,
lineJoin: 'round',
angle: 1,
radius: 30,
x: this.stage.getWidth() / 2,
y: 33,
rotation: -90,
shadowColor: 'black',
shadowOffset: 3,
shadowBlur: 2,
shadowOpacity: 0.5
});
// add components to the stage
this.layer.add(this.wheel);
this.layer.add(this.pointer);
this.stage.add(this.layer);
// bind events
this.bind();
var anim = new Konva.Animation(this.animate.bind(this), this.layer);
// wait one second and then spin the wheel
setTimeout(function () {
anim.start();
}, 1000);
}
}