七夕爱上女孩表白文字和鼠标特效
代码语言:html
所属分类:表白
代码描述:七夕爱上女孩表白文字和鼠标特效
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link href="https://fonts.googleapis.com/css2?family=Amatic+SC:wght@700&display=swap" rel="stylesheet"> <style> *, *::before, *::after{ box-sizing: border-box; margin: 0; padding: 0; } html, body{ display: block; position: relative; width: 100%; height: 100%; } canvas{ background: repeating-linear-gradient( 45deg, #2374C6, #2374C6 50px, #FFDD22 50px, #FFDD22 100px /* determines size */ ); display: block; cursor: crosshair; font-family: 'Amatic SC', cursive; } </style> </head> <body translate="no"> <canvas></canvas> <script> !function (universe) { const GLOBAL_DEFAULTS = { background: null, padding: 0, fontSize: 50, lineHeight: 100, lineWidth: 2, fontFamily: 'sans-serif', weight: 'normal', baseline: 'middle', pointerRadius: 10, textAlign: 'center', verticalAlignment: 'top', strokeStyle: 'red', fillStyle: 'black', compositeOperation: 'source-over', horizontalAlignment: 'left' }; class Util { static getWidest(strings, { fontSize, fontFamily } = {}) { let $canvas = document.createElement('canvas').getContext('2d'); $canvas.font = `${fontSize}px ${fontFamily}`; let widest = $canvas.measureText(strings[0]).width; for (let i = 1; i < strings.length; i++) { if ($canvas.measureText(strings[i]).width > widest) widest = $canvas.measureText(strings[i]).width; } $canvas = null; return widest; } static getStringWidth(string, { fontSize, fontFamily } = {}) { let $canvas = document.createElement('canvas').getContext('2d'); $canvas.font = `${fontSize}px ${fontFamily}`; let width = $canvas.measureText(string).width; $canvas = null; return width; } static pickRandom(choice) { return choice[~~(Math.random() * choice.length)]; } static randomInRange(min, max) { return Math.random() * (max - min) + min; }} class Component { constructor() { this.props = {}; //will hold flags and values to be shared with this component's children (e.g. mouse coordinates) } setProps(prop, value) {this.props[prop] = value;} getProp(prop) {return this.props[prop];} onUpdate(method) {this.update = method.bind(this);} onRender(method) {this.render = method.bind(this);} onMount(method) {this.mount = method.bind(this);}} class BoundedComponent extends Component { constructor(width, height, { position = { x: 0, y: 0 }, padding = GLOBAL_DEFAULTS.padding, verticalAlignment = GLOBAL_DEFAULTS.verticalAlignment, horizontalAlignment = GLOBAL_DEFAULTS.horizontalAlignment } = {}) { super(); this.width = width; this.height = height; this.position = position; this.renderingPosition = { x: null, y: null }; //will be calculated when the component is mounted in the scene this.padding = padding; this.verticalAlignment = verticalAlignment; this.horizontalAlignment = horizontalAlignment; } createSpaceProps(bounds) { const innerBounds = { x: null, y: null, w: null, h: null }; const renderingPosition = { x: null, y: null }; switch (this.verticalAlignment) { case 'top': innerBounds.y = bounds.y + this.padding; renderingPosition.y = bounds.y; break; case 'middle': innerBounds.y = bounds.y + bounds.h / 2 - this.height / 2 + this.padding; renderingPosition.y = bounds.y + bounds.h / 2 - this.height / 2; break; case 'bottom': innerBounds.y = bounds.y + bounds.h - this.height + this.padding; renderingPosition.y = bounds.y + bounds.h - this.height;} switch (this.horizontalAlignment) { case 'left': innerBounds.x = bounds.x + this.padding; renderingPosition.x = bounds.x; break; case 'center': innerBounds.x = bounds.x + bounds.w / 2 - this.width / 2 + this.padding; renderingPosition.x = bounds.x + bounds.w / 2 - this.width / 2; break; case 'right': innerBounds.x = bounds.x + bounds.w - this.width + this.padding; renderingPosition.x = bounds.x + bounds.w - this.width;} innerBounds.w = this.width - this.padding * 2; innerBounds.h = this.height - this.padding * 2; innerBounds.x += this.position.x; innerBounds.y += this.position.y; renderingPosition.x += this.position.x; renderingPosition.y += this.position.y; return { innerBounds, renderingPosition }; } drawMyOutline() {//for debugging const $ = this.getProp('sceneContext'); $.save(); $.strokeStyle = 'red'; $.setLineDash([5, 10]); $.lineWidth = 3; $.strokeRect(this.innerBounds.x, this.innerBounds.y, this.innerBounds.w, this.innerBounds.h); $.restore(); } setBounds(outerBounds = this.getParentProp('innerBounds')) { const spaceProps = this.createSpaceProps(outerBounds); this.innerBounds = spaceProps.innerBounds; this.renderingPosition = spaceProps.renderingPosition; this.setProps('innerBounds', this.innerBounds); }} class TextNode extends BoundedComponent { constructor(string, lineHeight, { position = { x: 0, y: 0 }, lineWidth = 0, fillStyle = GLOBAL_DEFAULTS.fillStyle, strokeStyle = GLOBAL_DEFAULTS.strokeStyle, padding = GLOBAL_DEFAULTS.padding, fontSize = GLOBAL_DEFAULTS.fontSize, fontFamily = GLOBAL_DEFAULTS.fontFamily, weight = GLOBAL_DEFAULTS.weight, verticalAlignment = GLOBAL_DEFAULTS.verticalAlignment, horizontalAlignment = GLOBAL_DEFAULTS.horizontalAlignment } = {}) { const width = Util.getStringWidth(string, { fontSize, fontFamily }); super(width, lineHeight, { position, padding, verticalAlignment, horizontalAlignment }); this.string = string; this.contextProps = { fontSize, fontFamily, weight, fillStyle, lineWidth, strokeStyle }; } createSpaceProps(bounds) { const innerBounds = { x: null, y: null, w: null, h: null }; const renderingPosition = { x: null, y: null }; switch (this.verticalAlignment) { case 'top': innerBounds.y = bounds.y + this.padding; renderingPosition.y = bounds.y + this.height / 2; break; case 'middle': innerBounds.y = bounds.y + bounds.h / 2 - this.height / 2 + this.padding; renderingPosition.y = bounds.y + bounds.h / 2; break; case 'bottom': innerBounds.y = bounds.y + bounds.h - this.height + this.padding; renderingPosition.y = bounds.y + bounds.h - this.height / 2;} switch (this.horizontalAlignment) { case 'left': innerBounds.x = bounds.x + this.padding; renderingPosition.x = bounds.x + this.width / 2; break; case 'center': innerBounds.x = bounds.x + bounds.w / 2 - this.width / 2 + this.padding; renderingPosition.x = bounds.x + bounds.w / 2; break; case 'right': innerBounds.x = bounds.x + bounds.w - this.width + this.padding; renderingPosition.x = bounds.x + bounds.w - this.width / 2;} innerBounds.w = this.width - this.padding * 2; innerBounds.h = this.height - this.padding * 2; innerBounds.x += this.position.x; innerBounds.y += this.position.y; renderingPosition.x += this.position.x; renderingPosition.y += this.position.y; return { innerBounds, renderingPosition }; } update() {} //kinda like an abstract method render() {} //same ^^^ } class Container extends BoundedComponent { constructor(width, height, { position = { x: 0, y: 0 }, padding = GLOBAL_DEFAULTS.padding, verticalAlignment = GLOBAL_DEFAULTS.verticalAlignment, horizontalAlignment = GLOBAL_DEFAULTS.horizontalAlignment } = {}) { super(width, height, { position, padding, verticalAlignment, horizontalAlignment }); this.components = []; } update() {} //again similar thing to an abstract method updateComponents() { for (let i = 0; i < this.components.length; i++) { const component = this.components[i]; if (!component.getProp('pointer')) {component.setProps('pointer', this.getProp('pointer'));} component.update(); if (component instanceof BoundedComponent) {component.setBounds();} if (component.components && component.components.length) {component.updateComponents();} } } applyContextProps({ lineWidth = GLOBAL_DEFAULTS.lineWidth, compositeOperation = GLOBAL_DEFAULTS.compositeOperation, strokeStyle = GLOBAL_DEFAULTS.strokeStyle, fillStyle = GLOBAL_DEFAULTS.fillStyle, fontSize = GLOBAL_DEFAULTS.fontSize, fontFamily = GLOBAL_DEFAULTS.fontFamily, weight = GLOBAL_DEFAULTS.weight } = {}) { const $ = this.getProp('sceneContext'); $.save(); $.strokeStyle = strokeStyle; $.fillStyle = fillStyle; $.lineWidth = lineWidth; $.globalCompositeOperation = compositeOperation; $.font = `${weight} ${fontSize}px ${fontFamily}`; } render() {} //yep, again... restoreSceneContext() { const $ = this.getProp('sceneContext'); $.restore(); } renderComponents() { for (let i = 0; i < this.components.length; i++) { const component = this.components[i]; if (component.contextProps) {this.applyContextProps(component.contextProps);} component.render(); if (component.contextProps) {this.restoreSceneContext();} if (component.components && component.components.length) {component.renderComponents();} } } addComponent(component) { component.setParentProp = this.setProps.bind(this); component.getParentProp = this.getProp.bind(this); if (!component.getProp('pointer')) {component.setProps('pointer', this.getProp('pointer'));} if (!component.getProp('sceneContext')) {component.setProps('sceneContext', this.getProp('sceneContext'));} if (component instanceof BoundedComponent) {component.setBounds();} if (component.mount) component.mount(); this.components.push(component); } addMulti(components) { for (let i = 0; i < components.length; i++) { this.addComponent(components[i]); } }} class Scene extends Container { constructor(canvas, { pointer = null, padding = GLOBAL_DEFAULTS.padding, background = GLOBAL_DEFAULTS.background } = {}) { super(canvas.width, canvas.height, { padding }); //set up the rendering canvas and it's context this.canvas = canvas; this.context = this.setBaseContext(canvas); //this will be passed down to other sub-components of the view if (pointer instanceof Pointer) this.pointer = this.initilisePointer(pointer); this.background = background; .........完整代码请登录后点击上方下载按钮下载查看
网友评论0