Skip to content

ICanvas - 语音录制波 ​

演示 ​

预览

介绍 ​

可能ILayout排版引擎可以对添加进的元素自动排版。

示例源码 ​

uvue
vue
<template>

	<!-- #ifdef MP-WEIXIN -->
	<page-meta :page-style="`background-color:${xThemeConfigBgColor}`">
		<navigation-bar :background-color="xThemeConfigNavBgColor"
			:front-color="xThemeConfigNavFontColor"></navigation-bar>
	</page-meta>
	<!-- #endif -->

	<x-sheet>
		<x-text font-size="18" class=" text-weight-b mb-8">自动排版</x-text>
		<x-text color="#999999" class="mb-8">通过shape元素clone一定数量后,再通过ILayout来自行排列,省去自动计算位置的繁琐操作。</x-text>

	</x-sheet>
	<x-sheet color="#000" dark-color="#000" :padding="['0']">
		<view class="xICanvasHost" :id="canvasId" :style="{height: canvasH + 'px'}">
			<x-skia-u ref="skiaRef" :width="canvasW" :height="canvasH" @ready="onSkiaReady"></x-skia-u>
			<view class="xICanvasHit"
				@click="bindEvents" @touchstart="bindEvents" @touchmove.stop="bindEvents"
				@touchend="bindEvents" @touchcancel="bindEvents" @mousedown="bindEvents"
				@mousemove="bindEvents" @mouseup="bindEvents"
				<!-- #ifdef WEB -->
				@mouseleave="bindEvents"
				<!-- #endif -->
			></view>
		</view>
	</x-sheet>


</template>

<script setup>
	import { ICanvas,CanvasEventType, ICanvasEvent ,ICanvasOptional ,ILine,ILayout,
	IRect,IText,Tween,ImageShape,Path2DShape,IRing,IArc,ISector,IRegularPolygon,
	ILinePolygon,ICircle,IEllipse,IStar,Easing,EasingFunction,GravityPlugin, GravityManager, addGravityToShape
	} from '@/uni_modules/tmx-ui';

	const canvasId = "xCanvas-" + Math.random().toString(16).substring(4)
	const canvasW = Math.max(1, Math.floor(uni.getWindowInfo().windowWidth))
	const canvasH = 450
	const skiaRef = ref(null)
	const proxy = getCurrentInstance()?.proxy ?? null;
	const xcanvas = shallowRef<ICanvas>(new ICanvas({ canvasId: canvasId, component: proxy as any | null } as ICanvasOptional));

	// 存储所有线条和动画
	let voiceLines : ILine[] = []
	let tweens : Tween[] = []

	const bindEvents = (evt : UniTouchEvent | UniPointerEvent | UniMouseEvent) => {
		xcanvas.value.bindEvent(evt)
	}


	// 初始化绘制
	const drawer = () => {
		if (xcanvas.value == null) return;
		const render = xcanvas.value! as ICanvas

		// 设置背景
		const bgRect = new IRect({
			x: 0,
			y: 0,
			width: render.boxWidth,
			height: render.boxHeight,
			fill: "#252a36"
		}, render)
		render.addShape(bgRect)

		const recttest = new IRect({
			x: 0,
			y: 0,
			width: 50,
			radius:8,
			height: 50,
			fill: '#00ccff'
		}, render)
		
		const shapesList = recttest.clone(24)
		render.addShape(shapesList)
		
		let layout = new ILayout(render)
		layout.setsPosition(50,50)
		layout.setsSize(layout.width - 100,layout.height - 100)
		layout.setsMode('between')
		layout.setsWrap(true)
		layout.addShape(shapesList)
		
		layout.render()
		render.render()
		shapesList.forEach((elrect,index)=>{
			// 为每条线创建不同的动画参数
			const animationDuration = 800 + Math.random() * 400 // 800-1200ms
			const delay = index * 50 // 错开动画时间
			// 创建高度变化动画
			const tween = new Tween(elrect, render)
				.delay(delay)
				.setLoop(-1)
				.onUpdate((progress:number) => {
					// 动态改变颜色
					const progressPec = Math.sin((Date.now()+animationDuration) * 0.005 + index * 0.5) * 0.5 + 0.5
					const colors = [
						'#00ff88',
						'#00ccff', 
						'#ff6b6b',
						'#37ff66',
						'#91ff62',
						'#5269ff',
						'#8026ff',
						'#aa00ff'
					]
					const colorIndex = Math.floor(progressPec * (colors.length - 1))
					elrect.setFill(colors[colorIndex])
					elrect.setRotateCenter('center')
					elrect.setScaleX(progressPec)
					elrect.setScaleY(progressPec)
				})
				.start()
			
			tweens.push(tween)
		})
		
	}

	const onSkiaReady = () => {
		const ctx = skiaRef.value?.getContext("2d")
		if (ctx == null) return
		xcanvas.value.onSurfaceReady(ctx, drawer)
	}

	onBeforeUnmount(() => {
		// 清理所有动画
		tweens.forEach(tween => {
			tween?.destroy()
		})
		tweens = [] as Tween[]
		xcanvas.value?.destroy()
	})
	
	
</script>

<style>
	.xICanvasHost { position: relative; width: 100%; overflow: hidden; }
	.xICanvasHit { position: absolute; left: 0; top: 0; right: 0; bottom: 0; }
</style>
最近更新