ng-cw-v12
Version:
Angular UI Component Library
413 lines (408 loc) • 20.1 kB
JavaScript
import * as i0 from '@angular/core';
import { Component, ViewChild, Input, HostListener, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
class ShapeGridBackgroundComponent {
constructor(ngZone) {
this.ngZone = ngZone;
/** 动画移动方向,可选值:right, left, up, down, diagonal */
this.ncDirection = 'diagonal';
/** 动画移动速度(0.1-2) */
this.ncSpeed = 0.5;
/** 网格边框颜色 */
this.ncBorderColor = '#271e37';
/** 形状大小(10-100) */
this.ncSquareSize = 40;
/** 悬停时的填充颜色 */
this.ncHoverFillColor = '#222222';
/** 形状类型,可选值:square, hexagon, triangle, circle */
this.ncShape = 'square';
/** 鼠标悬停尾迹长度(0-20) */
this.ncHoverTrailAmount = 0;
/** 背景色 */
this.ncBgColor = '#000000';
this.ctx = null;
this.rafId = null;
this.gridOffset = { x: 0, y: 0 };
this.hoveredSquare = null;
this.trailCells = [];
this.cellOpacities = new Map();
}
ngOnInit() { }
ngAfterViewInit() {
const canvas = this.canvasRef.nativeElement;
this.ctx = canvas.getContext('2d');
// 需要在zone外执行的代码用this.ngZone.runOutsideAngular,比如Canvas 更新
this.ngZone.runOutsideAngular(() => {
this.setupResizeObserver(canvas);
this.resizeCanvas();
this.updateAnimation();
});
}
ngOnDestroy() {
if (this.rafId !== null) {
cancelAnimationFrame(this.rafId);
this.rafId = null;
}
if (this.resizeObserver) {
this.resizeObserver.disconnect();
}
}
setupResizeObserver(canvas) {
this.resizeObserver = new ResizeObserver(() => {
this.resizeCanvas();
});
this.resizeObserver.observe(canvas.parentElement || canvas);
}
resizeCanvas() {
const canvas = this.canvasRef.nativeElement;
const parent = canvas.parentElement;
if (parent) {
canvas.width = parent.offsetWidth;
canvas.height = parent.offsetHeight;
}
}
drawHex(cx, cy, size) {
if (!this.ctx)
return;
this.ctx.beginPath();
for (let i = 0; i < 6; i++) {
const angle = (Math.PI / 3) * i;
const vx = cx + size * Math.cos(angle);
const vy = cy + size * Math.sin(angle);
if (i === 0)
this.ctx.moveTo(vx, vy);
else
this.ctx.lineTo(vx, vy);
}
this.ctx.closePath();
}
drawCircle(cx, cy, size) {
if (!this.ctx)
return;
this.ctx.beginPath();
this.ctx.arc(cx, cy, size / 2, 0, Math.PI * 2);
this.ctx.closePath();
}
drawTriangle(cx, cy, size, flip) {
if (!this.ctx)
return;
this.ctx.beginPath();
if (flip) {
this.ctx.moveTo(cx, cy + size / 2);
this.ctx.lineTo(cx + size / 2, cy - size / 2);
this.ctx.lineTo(cx - size / 2, cy - size / 2);
}
else {
this.ctx.moveTo(cx, cy - size / 2);
this.ctx.lineTo(cx + size / 2, cy + size / 2);
this.ctx.lineTo(cx - size / 2, cy + size / 2);
}
this.ctx.closePath();
}
drawGrid() {
const canvas = this.canvasRef.nativeElement;
const ctx = this.ctx;
if (!ctx)
return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
const isHex = this.ncShape === 'hexagon';
const isTri = this.ncShape === 'triangle';
const hexHoriz = this.ncSquareSize * 1.5;
const hexVert = this.ncSquareSize * Math.sqrt(3);
if (isHex) {
const colShift = Math.floor(this.gridOffset.x / hexHoriz);
const offsetX = ((this.gridOffset.x % hexHoriz) + hexHoriz) % hexHoriz;
const offsetY = ((this.gridOffset.y % hexVert) + hexVert) % hexVert;
const cols = Math.ceil(canvas.width / hexHoriz) + 3;
const rows = Math.ceil(canvas.height / hexVert) + 3;
for (let col = -2; col < cols; col++) {
for (let row = -2; row < rows; row++) {
const cx = col * hexHoriz + offsetX;
const cy = row * hexVert + ((col + colShift) % 2 !== 0 ? hexVert / 2 : 0) + offsetY;
const cellKey = `${col},${row}`;
const alpha = this.cellOpacities.get(cellKey);
if (alpha) {
ctx.globalAlpha = alpha;
this.drawHex(cx, cy, this.ncSquareSize);
ctx.fillStyle = this.ncHoverFillColor;
ctx.fill();
ctx.globalAlpha = 1;
}
this.drawHex(cx, cy, this.ncSquareSize);
ctx.strokeStyle = this.ncBorderColor;
ctx.stroke();
}
}
}
else if (isTri) {
const halfW = this.ncSquareSize / 2;
const colShift = Math.floor(this.gridOffset.x / halfW);
const rowShift = Math.floor(this.gridOffset.y / this.ncSquareSize);
const offsetX = ((this.gridOffset.x % halfW) + halfW) % halfW;
const offsetY = ((this.gridOffset.y % this.ncSquareSize) + this.ncSquareSize) % this.ncSquareSize;
const cols = Math.ceil(canvas.width / halfW) + 4;
const rows = Math.ceil(canvas.height / this.ncSquareSize) + 4;
for (let col = -2; col < cols; col++) {
for (let row = -2; row < rows; row++) {
const cx = col * halfW + offsetX;
const cy = row * this.ncSquareSize + this.ncSquareSize / 2 + offsetY;
const flip = ((col + colShift + row + rowShift) % 2 + 2) % 2 !== 0;
const cellKey = `${col},${row}`;
const alpha = this.cellOpacities.get(cellKey);
if (alpha) {
ctx.globalAlpha = alpha;
this.drawTriangle(cx, cy, this.ncSquareSize, flip);
ctx.fillStyle = this.ncHoverFillColor;
ctx.fill();
ctx.globalAlpha = 1;
}
this.drawTriangle(cx, cy, this.ncSquareSize, flip);
ctx.strokeStyle = this.ncBorderColor;
ctx.stroke();
}
}
}
else if (this.ncShape === 'circle') {
const offsetX = ((this.gridOffset.x % this.ncSquareSize) + this.ncSquareSize) % this.ncSquareSize;
const offsetY = ((this.gridOffset.y % this.ncSquareSize) + this.ncSquareSize) % this.ncSquareSize;
const cols = Math.ceil(canvas.width / this.ncSquareSize) + 3;
const rows = Math.ceil(canvas.height / this.ncSquareSize) + 3;
for (let col = -2; col < cols; col++) {
for (let row = -2; row < rows; row++) {
const cx = col * this.ncSquareSize + this.ncSquareSize / 2 + offsetX;
const cy = row * this.ncSquareSize + this.ncSquareSize / 2 + offsetY;
const cellKey = `${col},${row}`;
const alpha = this.cellOpacities.get(cellKey);
if (alpha) {
ctx.globalAlpha = alpha;
this.drawCircle(cx, cy, this.ncSquareSize);
ctx.fillStyle = this.ncHoverFillColor;
ctx.fill();
ctx.globalAlpha = 1;
}
this.drawCircle(cx, cy, this.ncSquareSize);
ctx.strokeStyle = this.ncBorderColor;
ctx.stroke();
}
}
}
else {
const offsetX = ((this.gridOffset.x % this.ncSquareSize) + this.ncSquareSize) % this.ncSquareSize;
const offsetY = ((this.gridOffset.y % this.ncSquareSize) + this.ncSquareSize) % this.ncSquareSize;
const cols = Math.ceil(canvas.width / this.ncSquareSize) + 3;
const rows = Math.ceil(canvas.height / this.ncSquareSize) + 3;
for (let col = -2; col < cols; col++) {
for (let row = -2; row < rows; row++) {
const sx = col * this.ncSquareSize + offsetX;
const sy = row * this.ncSquareSize + offsetY;
const cellKey = `${col},${row}`;
const alpha = this.cellOpacities.get(cellKey);
if (alpha) {
ctx.globalAlpha = alpha;
ctx.fillStyle = this.ncHoverFillColor;
ctx.fillRect(sx, sy, this.ncSquareSize, this.ncSquareSize);
ctx.globalAlpha = 1;
}
ctx.strokeStyle = this.ncBorderColor;
ctx.strokeRect(sx, sy, this.ncSquareSize, this.ncSquareSize);
}
}
}
const gradient = ctx.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, Math.sqrt(Math.pow(canvas.width, 2) + Math.pow(canvas.height, 2)) / 2);
gradient.addColorStop(0, 'rgba(0, 0, 0, 0)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
updateAnimation() {
const effectiveSpeed = Math.max(this.ncSpeed, 0.1);
const isHex = this.ncShape === 'hexagon';
const isTri = this.ncShape === 'triangle';
const hexHoriz = this.ncSquareSize * 1.5;
const hexVert = this.ncSquareSize * Math.sqrt(3);
const wrapX = isHex ? hexHoriz * 2 : this.ncSquareSize;
const wrapY = isHex ? hexVert : isTri ? this.ncSquareSize * 2 : this.ncSquareSize;
switch (this.ncDirection) {
case 'right':
this.gridOffset.x = (this.gridOffset.x - effectiveSpeed + wrapX) % wrapX;
break;
case 'left':
this.gridOffset.x = (this.gridOffset.x + effectiveSpeed + wrapX) % wrapX;
break;
case 'up':
this.gridOffset.y = (this.gridOffset.y + effectiveSpeed + wrapY) % wrapY;
break;
case 'down':
this.gridOffset.y = (this.gridOffset.y - effectiveSpeed + wrapY) % wrapY;
break;
case 'diagonal':
this.gridOffset.x = (this.gridOffset.x - effectiveSpeed + wrapX) % wrapX;
this.gridOffset.y = (this.gridOffset.y - effectiveSpeed + wrapY) % wrapY;
break;
default:
break;
}
this.updateCellOpacities();
this.drawGrid();
// animation loop
this.rafId = requestAnimationFrame(() => this.updateAnimation());
}
updateCellOpacities() {
const targets = new Map();
if (this.hoveredSquare) {
targets.set(`${this.hoveredSquare.x},${this.hoveredSquare.y}`, 1);
}
if (this.ncHoverTrailAmount > 0) {
for (let i = 0; i < this.trailCells.length; i++) {
const t = this.trailCells[i];
const key = `${t.x},${t.y}`;
if (!targets.has(key)) {
targets.set(key, (this.trailCells.length - i) / (this.trailCells.length + 1));
}
}
}
for (const [key] of targets) {
if (!this.cellOpacities.has(key)) {
this.cellOpacities.set(key, 0);
}
}
for (const [key, opacity] of this.cellOpacities) {
const target = targets.get(key) || 0;
const next = opacity + (target - opacity) * 0.15;
if (next < 0.005) {
this.cellOpacities.delete(key);
}
else {
this.cellOpacities.set(key, next);
}
}
}
onMouseMove(event) {
var _a;
const canvas = (_a = this.canvasRef) === null || _a === void 0 ? void 0 : _a.nativeElement;
if (!canvas)
return;
const rect = canvas.getBoundingClientRect();
const mouseX = event.clientX - rect.left;
const mouseY = event.clientY - rect.top;
const isHex = this.ncShape === 'hexagon';
const isTri = this.ncShape === 'triangle';
const hexHoriz = this.ncSquareSize * 1.5;
const hexVert = this.ncSquareSize * Math.sqrt(3);
let col = 0;
let row = 0;
if (isHex) {
const colShift = Math.floor(this.gridOffset.x / hexHoriz);
const offsetX = ((this.gridOffset.x % hexHoriz) + hexHoriz) % hexHoriz;
const offsetY = ((this.gridOffset.y % hexVert) + hexVert) % hexVert;
const adjustedX = mouseX - offsetX;
const adjustedY = mouseY - offsetY;
col = Math.round(adjustedX / hexHoriz);
const rowOffset = (col + colShift) % 2 !== 0 ? hexVert / 2 : 0;
row = Math.round((adjustedY - rowOffset) / hexVert);
}
else if (isTri) {
const halfW = this.ncSquareSize / 2;
const offsetX = ((this.gridOffset.x % halfW) + halfW) % halfW;
const offsetY = ((this.gridOffset.y % this.ncSquareSize) + this.ncSquareSize) % this.ncSquareSize;
const adjustedX = mouseX - offsetX;
const adjustedY = mouseY - offsetY;
col = Math.round(adjustedX / halfW);
row = Math.floor(adjustedY / this.ncSquareSize);
}
else if (this.ncShape === 'circle') {
const offsetX = ((this.gridOffset.x % this.ncSquareSize) + this.ncSquareSize) % this.ncSquareSize;
const offsetY = ((this.gridOffset.y % this.ncSquareSize) + this.ncSquareSize) % this.ncSquareSize;
const adjustedX = mouseX - offsetX;
const adjustedY = mouseY - offsetY;
col = Math.round(adjustedX / this.ncSquareSize);
row = Math.round(adjustedY / this.ncSquareSize);
}
else {
const offsetX = ((this.gridOffset.x % this.ncSquareSize) + this.ncSquareSize) % this.ncSquareSize;
const offsetY = ((this.gridOffset.y % this.ncSquareSize) + this.ncSquareSize) % this.ncSquareSize;
const adjustedX = mouseX - offsetX;
const adjustedY = mouseY - offsetY;
col = Math.floor(adjustedX / this.ncSquareSize);
row = Math.floor(adjustedY / this.ncSquareSize);
}
if (!this.hoveredSquare || this.hoveredSquare.x !== col || this.hoveredSquare.y !== row) {
if (this.hoveredSquare && this.ncHoverTrailAmount > 0) {
this.trailCells.unshift(Object.assign({}, this.hoveredSquare));
if (this.trailCells.length > this.ncHoverTrailAmount) {
this.trailCells.length = this.ncHoverTrailAmount;
}
}
this.hoveredSquare = { x: col, y: row };
}
}
onMouseLeave() {
if (this.hoveredSquare && this.ncHoverTrailAmount > 0) {
this.trailCells.unshift(Object.assign({}, this.hoveredSquare));
if (this.trailCells.length > this.ncHoverTrailAmount) {
this.trailCells.length = this.ncHoverTrailAmount;
}
}
this.hoveredSquare = null;
}
}
ShapeGridBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: ShapeGridBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
ShapeGridBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: ShapeGridBackgroundComponent, selector: "nc-shape-grid-background", inputs: { ncDirection: "ncDirection", ncSpeed: "ncSpeed", ncBorderColor: "ncBorderColor", ncSquareSize: "ncSquareSize", ncHoverFillColor: "ncHoverFillColor", ncShape: "ncShape", ncHoverTrailAmount: "ncHoverTrailAmount", ncBgColor: "ncBgColor" }, host: { listeners: { "mousemove": "onMouseMove($event)", "mouseleave": "onMouseLeave()" } }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvas"], descendants: true, static: true }], ngImport: i0, template: "<canvas #canvas class=\"nc-shape-grid-canvas\" [style.background-color]=\"ncBgColor\"></canvas>\r\n<div class=\"nc-content-wrapper\">\r\n <ng-content></ng-content>\r\n</div>", styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}.nc-shape-grid-canvas{position:absolute;inset:0;z-index:0;width:100%;height:100%;border:none;display:block;pointer-events:none}.nc-content-wrapper{position:relative;z-index:1;width:100%;height:100%}\n"] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: ShapeGridBackgroundComponent, decorators: [{
type: Component,
args: [{
selector: 'nc-shape-grid-background',
templateUrl: './shape-grid-background.component.html',
styleUrls: ['./shape-grid-background.component.less']
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { canvasRef: [{
type: ViewChild,
args: ['canvas', { static: true }]
}], ncDirection: [{
type: Input
}], ncSpeed: [{
type: Input
}], ncBorderColor: [{
type: Input
}], ncSquareSize: [{
type: Input
}], ncHoverFillColor: [{
type: Input
}], ncShape: [{
type: Input
}], ncHoverTrailAmount: [{
type: Input
}], ncBgColor: [{
type: Input
}], onMouseMove: [{
type: HostListener,
args: ['mousemove', ['$event']]
}], onMouseLeave: [{
type: HostListener,
args: ['mouseleave']
}] } });
class NcShapeGridBackgroundModule {
}
NcShapeGridBackgroundModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcShapeGridBackgroundModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
NcShapeGridBackgroundModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcShapeGridBackgroundModule, declarations: [ShapeGridBackgroundComponent], imports: [CommonModule], exports: [ShapeGridBackgroundComponent] });
NcShapeGridBackgroundModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcShapeGridBackgroundModule, imports: [[
CommonModule
]] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcShapeGridBackgroundModule, decorators: [{
type: NgModule,
args: [{
declarations: [
ShapeGridBackgroundComponent
],
imports: [
CommonModule
],
exports: [
ShapeGridBackgroundComponent
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { NcShapeGridBackgroundModule, ShapeGridBackgroundComponent };
//# sourceMappingURL=ng-cw-v12-shape-grid-background.js.map