import type { AmbientLightProps, DirectionalLightProps } from '@antv/g-plugin-3d';
import { AmbientLight, DirectionalLight } from '@antv/g-plugin-3d';
import type { BasePluginOptions, RuntimeContext } from '@antv/g6';
import { BasePlugin, GraphEvent } from '@antv/g6';
import { deepMix } from '@antv/util';
/**
* 光照插件配置项
*
* Light plugin options
*/
export interface LightOptions extends BasePluginOptions {
/**
* 环境光
*
* Ambient light
*/
ambient?: AmbientLightProps;
/**
* 平行光
*
* Directional light
*/
directional?: DirectionalLightProps;
}
/**
* 光照插件
*
* Light plugin
*/
export class Light extends BasePlugin {
static defaultOptions: Partial = {
ambient: {
fill: '#fff',
intensity: Math.PI * 2,
},
directional: {
fill: '#fff',
direction: [-1, 0, 1],
intensity: Math.PI * 0.7,
},
};
private ambient?: AmbientLight;
private directional?: DirectionalLight;
constructor(context: RuntimeContext, options: LightOptions) {
super(context, deepMix({}, Light.defaultOptions, options));
this.bindEvents();
}
private bindEvents() {
this.context.graph.on(GraphEvent.BEFORE_DRAW, this.setLight);
}
private unbindEvents() {
this.context.graph.off(GraphEvent.BEFORE_DRAW, this.setLight);
}
private setLight = () => {
const { ambient, directional } = this.options;
this.upsertLight('directional', directional);
this.upsertLight('ambient', ambient);
};
private upsertLight(type: 'ambient', options?: AmbientLightProps): void;
private upsertLight(type: 'directional', options?: DirectionalLightProps): void;
private upsertLight(type: 'ambient' | 'directional', options?: AmbientLightProps | DirectionalLightProps) {
if (options) {
const light = this[type];
if (light) light.attr(options);
else {
const Ctor = type === 'ambient' ? AmbientLight : DirectionalLight;
const light = new Ctor({ style: options });
this[type] = light as any;
this.context.canvas.appendChild(light);
}
} else this[type]?.remove();
}
/**
* 销毁插件
*
* Destroy the plugin
* @internal
*/
public destroy() {
this.ambient?.remove();
this.directional?.remove();
this.unbindEvents();
super.destroy();
}
}