我是d3.js(v5)和angular(v7)的新手,我的问题是每当我调用multiFormat函数格式化日期时,“ this”变得不确定。
我试图直接将此this.d3传递给multiFormat,并且可以使用,但是在这种情况下,我不知道如何传递日期参数... 解决该问题的方法是在addXandYAxis内部声明multiFormat函数并使用所有参数
private addXandYAxis() {
const d3 = this.d3;
let dmax = d3.extent(this.data, d => d3.timeParse('%d/%m/%Y')(d.date));
dmax[0] = dmax[0].setMonth(dmax[0].getMonth() - 1);
// definition des domains de X & Y
const xDomain = this.data.map(d => d.date);
const yDomain = [0, this.d3.max(this.data, d => d.Donnees)];
// localisation des dates
const locale = this.d3.timeFormatLocale({
dateTime: '%A, %e %B %Y г. %X',
date: '%d.%m.%Y',
time: '%H:%M:%S',
periods: ['AM', 'PM'],
days: ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'],
shortDays: ['lu', 'ma', 'me' , 'je', 've', 'sa', 'di'],
months: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Decembre'],
shortMonths: ['janv.', 'févr.', 'mars', 'avr', 'mai', 'juin', 'juill.' , 'août' , 'sept.' , 'oct.' , 'nov.' , 'déc.' ]
});
const formatMillisecond = locale.format('.%L');
const formatSecond = locale.format(':%S');
const formatMinute = locale.format('%I:%M');
const formatHour = locale.format('%I %p');
const formatDay = locale.format('%a %d');
const formatWeek = locale.format('%b %d');
const formatMonth = locale.format('%B');
const formatYear = locale.format('%Y');
function multiFormat(date) {
console.log('date=' + date);
return(d3.timeSecond(date) < date ? formatMillisecond
: d3.timeMinute(date) < date ? formatSecond
: d3.timeHour(date) < date ? formatMinute
: d3.timeDay(date) < date ? formatHour
: d3.timeMonth(date) < date ? (d3.timeWeek(date) < date ? formatDay : formatWeek)
: d3.timeYear(date) < date ? formatMonth
: formatYear)(date);
}
我需要在其他地方使用multiFormat,并且我希望避免重复。 我在ngOnInit()中使用addXandYAxis,我的代码是
public addXandYAxis() {
const d3 = this.d3;
const dmax = d3.extent(this.data, d => d3.timeParse('%d/%m/%Y')(d.date));
// define X & Y domains
const xDomain = this.data.map(d => d.date);
const yDomain = [0, this.d3.max(this.data, d => d.Donnees)];
// Abscisse --> date
this.x = d3.scaleTime()
.domain(dmax)
.range([ 0, this.width ]);
this.xAxis = d3.axisBottom(this.x);
this.svg.append('g')
.attr('transform', 'translate(0,' + this.height + ')')
.call(this.xAxis.tickFormat(this.multiFormat));
}
private multiFormat(date) {
return(this.d3.timeSecond(date) < date ? this.formatMillisecond
: this.d3.timeMinute(date) < date ? this.formatSecond
: this.d3.timeHour(date) < date ? this.formatMinute
: this.d3.timeDay(date) < date ? this.formatHour
: this.d3.timeMonth(date) < date ? (this.d3.timeWeek(date) < date ? this.formatDay : this.formatWeek)
: this.d3.timeYear(date) < date ? this.formatMonth
: this.formatYear)(date);
}
结果为错误TypeError:“ this.d3未定义”
感谢您的时间:)
答案 0 :(得分:1)
您可以使用闭包来调用multiFormat 所以你可以这样做
import pygame
import pygame.freetype
import random
# a dict that defines the controls
# w moves up, s moves down etc
CONTROLS = {
pygame.K_w: ( 0, -1),
pygame.K_s: ( 0, 1),
pygame.K_a: (-1, 0),
pygame.K_d: ( 1, 0)
}
# a function that handles the behaviour a sprite that
# should be controled with the keys defined in CONTROLS
def keyboard_controlled_b(player, events, dt):
# let's see which keys are pressed, and create a
# movement vector from all pressed keys.
move = pygame.Vector2()
pressed = pygame.key.get_pressed()
for vec in (CONTROLS[k] for k in CONTROLS if pressed[k]):
move += vec
if move.length():
move.normalize_ip()
move *= (player.speed * dt/10)
# apply the movement vector to the position of the player sprite
player.pos += move
player.rect.center = player.pos
# a function that let's a sprite follow another one
# and kill it if they touch each other
def zombie_runs_to_target_b(target):
def zombie_b(zombie, events, dt):
if target.rect.colliderect(zombie.rect):
zombie.kill()
return
move = target.pos - zombie.pos
if move.length():
move.normalize_ip()
move *= (zombie.speed * dt/10)
zombie.pos += move
zombie.rect.center = zombie.pos
return zombie_b
# a simple generic sprite class that displays a simple, colored rect
# and invokes the given behaviour
class Actor(pygame.sprite.Sprite):
def __init__(self, color, pos, size, behavior, speed, *grps):
super().__init__(*grps)
self.image = pygame.Surface(size)
self.image.fill(color)
self.rect = self.image.get_rect(center=pos)
self.pos = pygame.Vector2(pos)
self.behavior = behavior
self.speed = speed
def update(self, events, dt):
self.behavior(self, events, dt)
# a sprite class that displays a timer
# when the timer runs out, a function is invoked
# and this sprite is killed
class WaveCounter(pygame.sprite.Sprite):
font = None
def __init__(self, time_until, action, *grps):
super().__init__(grps)
self.image = pygame.Surface((300, 50))
self.image.fill((3,2,1))
self.image.set_colorkey((3, 2, 1))
self.rect = self.image.get_rect(topleft=(10, 10))
if not WaveCounter.font:
WaveCounter.font = pygame.freetype.SysFont(None, 32)
WaveCounter.font.render_to(self.image, (0, 0), f'new wave in {time_until}', (255, 255, 255))
self.timer = time_until * 1000
self.action = action
def update(self, events, dt):
self.timer -= dt
self.image.fill((3,2,1))
WaveCounter.font.render_to(self.image, (0, 0), f'new wave in {int(self.timer / 1000) + 1}', (255, 255, 255))
if self.timer <= 0:
self.action()
self.kill()
def main():
pygame.init()
screen = pygame.display.set_mode((600, 480))
screen_rect = screen.get_rect()
clock = pygame.time.Clock()
dt = 0
sprites_grp = pygame.sprite.Group()
zombies_grp = pygame.sprite.Group()
wave_tm_grp = pygame.sprite.GroupSingle()
# the player is controlled with the keyboard
player = Actor(pygame.Color('dodgerblue'),
screen_rect.center,
(32, 32),
keyboard_controlled_b,
5,
sprites_grp)
# this function should be invoked once the timer runs out
def create_new_wave_func():
# let's create a bunch of zombies that follow the player
for _ in range(15):
x = random.randint(0, screen_rect.width)
y = random.randint(-100, 0)
Actor((random.randint(180, 255), 0, 0),
(x, y),
(26, 26),
zombie_runs_to_target_b(player),
random.randint(2, 4),
sprites_grp, zombies_grp)
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
# no timer, no zombies => create new timer
if len(wave_tm_grp) == 0 and len(zombies_grp) == 0:
WaveCounter(5, create_new_wave_func, sprites_grp, wave_tm_grp)
sprites_grp.update(events, dt)
screen.fill((80, 80, 80))
sprites_grp.draw(screen)
pygame.display.flip()
dt = clock.tick(60)
if __name__ == '__main__':
main()
因为'this'引用了调用函数的范围
答案 1 :(得分:0)
通常,this
的问题可以通过将有问题的功能转换为箭头功能来解决:
public addXandYAxis = () => {
// ...
private multiFormat = (date) => {
// ...