uniapp - 小程序实现摄像头拍照 + 水印绘制 + 反转摄像头 + 拍之前显示时间+地点 + 图片上传到阿里云服务器

前言

uniapp,碰到新需求,反转摄像头,需要在打卡的时候对上传图片加上水印,拍照前就显示当前时间日期+地点,拍摄后在呈现刚才拍摄的图加上水印,最好还需要将图片上传到阿里云。

声明

水印部分代码是借鉴的这位博主的博客,剩下的是我根据自己的需求加上的。水印部分看原博主博客就行。
小晗同学 - 原小程序拍照+水印绘制博主博客链接跳转

效果预览

拍摄前预览
右上角切换前后摄像头
底部时间和位置信息,这里位置替换掉真实位置了,代码里没变
在这里插入图片描述
拍摄后效果
在这里插入图片描述

水印组件代码

<template>
    <view class="camera-wrapper">
        <!-- 拍照 -->
        <template v-if="!snapSrc">
            <!-- 相机 -->
            <camera :device-position="cameraPosition" flash="off" @error="handleError" class="image-size">
                <view class="photo-btn" @click="handleTakePhoto">拍照</view>
                <view class="iconfont icon-qiehuanshexiangtou switch-camera-btn" @click="handleSwitchCamera"></view>
                <view class="time-wrap">
                    <view>{{ new Date().toLocaleString() }}</view>
                    <view>{{ location_data }}</view>
                    <!-- <view>这里是位置信息,</view> -->
                </view>
            </camera>
            <!-- 水印 -->
            <canvas canvas-id="photoMarkCanvas" id="photoMarkCanvas" class="mark-canvas"
                :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }" />
        </template>
        <!-- 预览 -->
        <template v-else>
            <!-- <view class="re-photo-btn btn" @click="handleRephotograph">重拍</view> -->
            <!-- <view class="re-fanhui-btn btn" @click="fanhui">返回</view> -->
            <image class="image-size" :src="snapSrc"></image>
        </template>
    </view>
</template>
<script>
const util_two = require('../../static/utils/util_two.js')
const upload = require('../../static/utils/upload.js')
export default {
    name: 'CameraSnap',
    props: {
        // 照片地址(若传递了照片地址,则默认为预览该照片或添加水印后预览)
        photoSrc: {
            type: String,
            default: ""
        },
        // 水印类型
        markType: {
            type: String,
            default: "fixed", // 定点水印 fixed,背景水印 background
        },
        // 水印文本列表(支持多行)
        markList: {
            type: Array,
            default: () => []
        },
        textColor: {
            type: String,
            default: "#FFFFFF"
        },
        textSize: {
            type: Number,
            default: 32
        },
        // 定点水印的遮罩(为了让水印更清楚)
        useTextMask: {
            type: Boolean,
            default: true
        }
    },
    data() {
        return {
            snapSrc: "",
            canvasWidth: "",
            canvasHeight: "",
            cameraPosition: 'back', // 默认为后置摄像头
            inputText: "", // 用户输入的文本
            location: null, // 存储位置信息
            location_data: "",

            photocount: 10,
            hasUserInfo: false,
            productInfo: [],
            fileurl: [],
            prveImgInfo: [],
            imgs: [],
            arrImg: [],
            imgQueRemData: [],//确实上传数据源
            // 位置和时间日期
        }
    },
    watch: {
        photoSrc: {
            handler: function (newValue, oldValue) {
                if (newValue) {
                    this.getWaterMarkImgPath(newValue)
                }
            },
            immediate: true
        }
    },
    mounted() {
        uni.getLocation({
            type: 'wgs84', // 获取经纬度坐标
            success: (res) => {
                this.location = res;
                setTimeout(() => {
                    this.GetMapData();
                }, 1000);
            },
            fail: (err) => {
                console.error('获取位置信息失败', err);
            }
        });
    },
    methods: {

        closeCamera() {
            this.$emit('close'); // 发送一个事件通知父组件关闭 CameraSnap 组件
        },
        handleTakePhoto() {
            // const that = this
            const ctx = uni.createCameraContext();
            ctx.takePhoto({
                quality: 'high',
                success: (res) => {
                    const imgPath = res.tempImagePath
                    if (this.markList.length) {
                        this.getWaterMarkImgPath(imgPath)
                        this.$emit('watermarkPath', this.snapSrc);

                    } else {
                        this.snapSrc = imgPath;
                        this.$emit('complete', imgPath)
                        this.$emit('watermarkPath', this.snapSrc);
                    }
                }
            });
        },
        handleRephotograph() {
            this.snapSrc = ""
        },
        handleSwitchCamera() {
            this.cameraPosition = this.cameraPosition === 'front' ? 'back' : 'front'; // 切换摄像头
        },
        handleError(err) {
            uni.showModal({
                title: '警告',
                content: '若不授权使用摄像头,将无法使用拍照功能!',
                cancelText: '不授权',
                confirmText: '授权',
                success: (res) => {
                    if (res.confirm) {
                        // 允许打开授权页面,调起客户端小程序设置界面,返回用户设置的操作结果
                        uni.openSetting({
                            success: (res) => {
                                res.authSetting = { "scope.camera": true }
                            },
                        })
                    } else if (res.cancel) {
                        // 拒绝打开授权页面
                        uni.showToast({ title: '您已拒绝授权,无法进行拍照', icon: 'error', duration: 2500 });
                    }
                }
            })
        },
        setWaterMark(context, image) {
            const listLength = this.markList?.length
            switch (this.markType) {
                case 'fixed':
                    const spacing = 6 // 行间距
                    const paddingTopBottom = 60 // 整体上下间距
                    // 默认每行的高度 = 字体高度 + 向下间隔
                    const lineHeight = this.textSize + spacing
                    const allLineHeight = lineHeight * listLength
                    // 矩形遮罩的 Y 坐标
                    const maskRectY = image.height - allLineHeight
                    // 绘制遮罩层
                    if (this.useTextMask) {
                        context.setFillStyle('rgba(0,0,0,0.4)');
                        context.fillRect(0, maskRectY - paddingTopBottom, image.width, allLineHeight + paddingTopBottom)
                    }
                    // 文本与 x 轴之间的间隔
                    const textX = 40
                    // 文本一行的最大宽度(减去 20 是为了一行的左右留间隙)
                    const maxWidth = image.width - 20
                    context.setFillStyle(this.textColor)
                    context.setFontSize(this.textSize)
                    this.markList.forEach((item, index) => {
                        // 因为文本的 Y 坐标是指文本基线的 Y 轴坐标,所以要获取文本顶部的 Y 坐标
                        const textY = maskRectY - paddingTopBottom / 2 + this.textSize + lineHeight * index
                        context.fillText(item, textX, textY, maxWidth);
                    })
                    break;
                case 'background':
                    context.translate(0, 0);
                    context.rotate(30 * Math.PI / 180);
                    context.setFillStyle(this.textColor)
                    context.setFontSize(this.textSize)
                    const colSize = parseInt(image.height / 6)
                    const rowSize = parseInt(image.width / 2)
                    let x = -rowSize
                    let y = -colSize
                    // 循环绘制 5 行 6 列 的文字
                    for (let i = 1; i <= 6; i++) {
                        for (let j = 1; j <= 5; j++) {
                            context.fillText(this.markList[0], x, y, rowSize)
                            // 每个水印间隔 20
                            x += rowSize + 20
                        }
                        y += colSize
                        x = -rowSize
                    }
                    break;
            }
            context.save();
        },
        getWaterMarkImgPath(src) {
            const _this = this
            uni.getImageInfo({
                src,
                success: (image) => {
                    this.canvasWidth = image.width
                    this.canvasHeight = image.height
                    const context = uni.createCanvasContext("photoMarkCanvas", this)
                    context.drawImage(src, 0, 0, image.width, image.height)
                    // 设置水印
                    this.setWaterMark(context, image)
                    // 若还需其他操作,可在操作之后叠加保存:context.restore()
                    // 将画布上的图保存为图片
                    context.draw(false, () => {
                        setTimeout(() => {
                            uni.canvasToTempFilePath({
                                destWidth: image.width,
                                destHeight: image.height,
                                canvasId: 'photoMarkCanvas',
                                fileType: 'jpg',
                                success: function (res) {
                                    console.log("将画布上的图保存为图片", JSON.parse(JSON.stringify(res)));
                                    _this.snapSrc = res.tempFilePath
                                    const tempFilePath = res.tempFilePath;
                                    const tempFilePathArray = [tempFilePath];
                                    _this.uploadimg({
                                        path: tempFilePathArray //这里是选取的图片的地址数组
                                    });
                                    _this.$emit('complete', _this.snapSrc)
                                }
                            },
                                _this
                            );
                        }, 200)
                    });
                }
            })
        },
        fanhui() {
            this.closeCamera();
        },
        sendUploadedImagesToParent() {
            this.$emit('imagesUploaded', this.prveImgInfo);
            // prveImgInfo  imgs
        },
        //多张图片上传  服务器
        uploadimg: function (data) {
            // 这两个是对应的,传递的就是这个路径
            var that = this;
            // var orderid = that.XmID;//项目id
            var orderid = '';
            // var gsid = '';
            let photocount = 9;
            var i = data.i ? data.i : 0; //当前上传的哪张图片
            var success = data.success ? data.success : 0; //上传成功的个数
            var fail = data.fail ? data.fail : 0; //上传失败的个数
            //上传到阿里云
            util_two.request(uni.$baseUrlweb + '/api/xcx/oss/fankui').then(function (result) {
                if (result.code == 0) {
                    // var filePath = data.path;
                    var filePath = data.path[i];
                    var filename = result.dir + orderid + upload.calculate_object_name(filePath, '');
                    uni.uploadFile({
                        url: result.host,
                        filePath: filePath,
                        name: "file",
                        /**上传的参数**/
                        formData: {
                            'key': filename, // 文件名
                            'policy': result.policy,
                            'OSSAccessKeyId': result.accessid,
                            'success_action_status': "200",
                            'signature': result.signature,
                            'callback': result.callback
                        },
                        success: (resp) => {
                            if (resp.statusCode == "200") {
                                success++; //图片上传成功,图片上传成功的变量+1
                                photocount--;
                                var show_url = result.host + '/' + filename + result.style1;
                                var productInfo = that.productInfo;
                                productInfo.push(show_url);
                                var prve_url = result.host + '/' + filename + result.style2;
                                var prveImgInfo = that.prveImgInfo;
                                prveImgInfo.push(prve_url);
                                that.sendUploadedImagesToParent();
                                var up_url = filename;
                                var fileurl = that.fileurl;
                                fileurl.push(up_url);
                                let n = i + 1;
                                uni.showLoading({
                                    title: n + '/' + data.path.length + '上传成功', //这里打印出 上传成功
                                })
                            }
                        },
                        fail: (res) => {
                            fail++; //图片上传失败,图片上传失败的变量+1
                            uni.showLoading({
                                title: (i + 1) + '/' + data.path.length + '上传失败', //这里打印出 上传成功
                            })
                        },
                        complete: (res) => {
                            i++; //这个图片执行完上传后,开始上传下一张
                            if (i == data.path.length) { //当图片传完时,停止调用     
                                // 添加上传数据
                                that.imgQueRemData.push(filename)
                                // 添加到展示数组
                                const path = result.host + '/' + filename + result.style1
                                that.arrImg.push(path)
                                that.imgs.push(path)

                                uni.hideLoading();
                                that.closeCamera();
                                if (success == i) {
                                    uni.showToast({
                                        title: '组图上传完成', //这里打印出 上传成功
                                        icon: 'success',
                                        duration: 1000
                                    })
                                } else {
                                    uni.showModal({
                                        title: '组图上传失败', //这里打印出 上传成功
                                        content: '请稍后再试',
                                        showCancel: false
                                    })
                                }
                            } else { //若图片还没有传完,则继续调用函数
                                data.i = i;
                                data.success = success;
                                data.fail = fail;
                                that.uploadimg(data);
                            }
                        }
                    });
                }
            })
        },
        // 获取具体位置信息
        async GetMapData() {
            const res = await this.$axios("work/getMap", {
                lat: this.location.latitude,
                lon: this.location.longitude
            });
            if (res.data.code == 0) {
                this.location_data = res.data.result;
            } else {
                uni.showToast({
                    title: res.data.msg,
                    icon: 'none',
                    duration: 1000
                })
            }
        },
    }
}
</script>
<style lang="scss" scoped>
.icon-qiehuanshexiangtou {
    font-size: 30px;
}

.camera-wrapper {
    position: relative;
}

.switch-camera-btn {
    position: absolute;
    top: 20px;
    right: 20px;
    color: #fff;
    font-size: 16px;
    cursor: pointer;
}

.mark-canvas {
    position: absolute;
    /* 将画布移出展示区域 */
    top: -200vh;
    left: -200vw;
}

.image-size {
    width: 100%;
    height: 100vh;
}

.photo-btn {
    position: absolute;
    bottom: 120rpx;
    left: 50%;
    transform: translateX(-50%);
    width: 140rpx;
    height: 140rpx;
    line-height: 140rpx;
    text-align: center;
    background-color: #000000;
    border-radius: 50%;
    border: 10rpx solid #ffffff;
    color: #fff;
}

.btn {
    padding: 10rpx 20rpx;
    background-color: #000000;
    border-radius: 10%;
    border: 6rpx solid #ffffff;
    color: #fff
}

.re-photo-btn {
    position: absolute;
    bottom: 150rpx;
    right: 40rpx;

}

.re-fanhui-btn {
    position: absolute;
    bottom: 150rpx;
    right: 180rpx;


}

.re-fanhui-tijao {
    position: absolute;
    bottom: 150rpx;
    right: 320rpx;

}

.time-wrap {
    position: absolute;
    left: 1rem;
    bottom: 1rem;
    color: white;
}
</style>

使用水印相机组件代码

<template>
	<view>
	    <view class="qianDao_img">
			<view class="imgs">
				<view style="margin-right: 10px;">
					照片:
				</view>
				<view @click="paizhao" class="paizhao">
					<view class="iconfont icon-paizhao1"></view>
				</view>
			</view>
			<view class="img_wrap">
				<image v-for="(item, index) in shuiyinImg" :key="index" :src="item" mode="scaleToFill"
					@click="SYpreviewImage(index)" @longpress="SYdeleteImage(index)" />
			</view>
		</view>

		<!-- <button @click="paizhao">拍照</button> -->
		<view class="full-screen" v-if="paizhaoType">
			<CameraSnap @imagesUploaded="handleImagesUploaded" @close="paizhaoType = false"
				:mark-list="[new Date().toLocaleString(), location_data]" textSize="24" useTextMask />
		</view>
		<view class="Bom_Btn">
			<view @click="BaoCunAction" class="Bom_Btn_log">
				<view>提交</view>
			</view>
		</view>
	</view>
</template>

<script>


import CameraSnap from '../CameraSnap.vue'

export default {
	data() {
		return {
			paizhaoType: false,
			location: null, // 存储位置信息
			location_data: "",
			// 水印图片
			shuiyinImg: '',
		};
	},
	components: {
		CameraSnap,
	},
	onLoad(options) {
		uni.getLocation({
			type: 'wgs84', // 获取经纬度坐标
			success: (res) => {
				this.location = res;
				setTimeout(() => {
					this.GetMapData();
				}, 1000);
			},
			fail: (err) => {
				console.error('获取位置信息失败', err);
			}
		});
	},

	methods: {
	    // 这里是水印图片
		handleImagesUploaded(images) {
			console.log("成功上传的图片数据:", images);
			this.shuiyinImg = [...this.shuiyinImg, ...images];
		},
		paizhao() {
			this.paizhaoType = true;
		},
		// 获取具体位置信息
		async GetMapData() {
			const res = await this.$axios("work/getMap", {
				lat: this.location.latitude,
				lon: this.location.longitude
			});
			if (res.data.code == 0) {
				this.location_data = res.data.result;
			} else {
				uni.showToast({
					title: res.data.msg,
					icon: 'none',
					duration: 1000
				})
			}
		},
		// 水印图片预览
		SYpreviewImage(index) {
			uni.previewImage({
				urls: this.shuiyinImg,
				current: index, // 当前显示图片的索引
				loop: true // 是否开启图片轮播
			});
		},
		// 长按删除水印图片
		SYdeleteImage(index) {
			uni.showModal({
				title: '提示',
				content: '确定要删除这张图片吗?',
				success: (res) => {
					if (res.confirm) {
						this.shuiyinImg.splice(index, 1);
					}
				}
			});
		},
	
	
		
		
	}
}
</script>

<style lang="scss" scoped>
.full-screen {
	position: fixed;
	top: 0;
	left: 0;
	width: 100vw;
	height: 100vh;
	// background-color: rgba(0, 0, 0, 0.5); /* 半透明背景 */
	z-index: 9999;
	/* 确保在最顶层显示 */
}

// 签到图片
.qianDao_img {
	// padding: 15px;
	border-top: 1px solid #dddddf;
	background-color: white;

	// 图片
	.imgs {
		padding: 15px;
		display: flex;
		align-items: center;
		flex-wrap: wrap;

	}

	.img_wrap {
		padding: 10px;
		display: flex;
		// justify-content: space-around;
		flex-wrap: wrap;

		image {
			width: 80px;
			height: 80px;
			margin-bottom: 5px;
			margin: 4px;
		}
	}

	// 上传图片
	.paizhao {
		width: 80px;
		height: 80px;
		// border: 1px solid red;
		margin: 10px 0;
		background-color: #f7f8fa;

		.icon-paizhao1 {
			// border: 1px solid red;
			width: 50%;
			font-size: 22px;
			padding-left: 25px;
			padding-top: 25px;
		}
	}
}

.Bom_Btn {
	width: 100%;
	padding: 10px;
	position: absolute;
	bottom: 0;
	left: 0;
	border-top: 1px solid #ededed;
	background-color: white;
	z-index: 2;

	.Bom_Btn_log {
		width: 70%;
		// display: flex;
		// align-items: center;
		// justify-content: center;
		// margin: auto;
		padding: 10px 0;
		margin: auto;
	}

	view {
		border-radius: 5px;
		text-align: center;
		color: white;
		background-color: #1989fa;
	}
}
</style>

只能说勉强够用,算不上精细,凑合看把,引入的两个js文件 都是辅助上传阿里云图片的,就是格式啥的进行校验,就没必要上传了,看懂整个思路就行,具体代码肯定还是需要根据自己的情况进行改动的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/945869.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图像处理-Ch7-小波函数

个人博客&#xff01;无广告观看&#xff0c;因为这节内容太多了&#xff0c;有点放不下&#xff0c;分了三节 文章目录 多分辨率展开(Multi-resolution Expansions)序列展开(Series Expansions)尺度函数(Scaling Function)例&#xff1a;哈尔尺度函数(Haar scaling func)多分…

本地小主机安装HomeAssistant开源智能家居平台打造个人AI管家

文章目录 前言1. 添加镜像源2. 部署HomeAssistant3. HA系统初始化配置4. HA系统添加智能设备4.1 添加已发现的设备4.2 添加HACS插件安装设备 5. 安装cpolar内网穿透5.1 配置HA公网地址 6. 配置固定公网地址 前言 大家好&#xff01;今天我要向大家展示如何将一台迷你的香橙派Z…

Rocky Linux下安装meld

背景介绍&#xff1a; meld是一款Linux系统下的用于 文件夹和文件的比对软件&#xff0c;非常常用&#xff1b; 故障现象&#xff1a; 输入安装命令后&#xff0c;sudo yum install meld&#xff0c;报错。 12-31 22:12:17 ~]$ sudo yum install meld Last metadata expirat…

数据结构与算法之动态规划: LeetCode 337. 打家劫舍 III (Ts版)

打家劫舍 III https://leetcode.cn/problems/house-robber-iii/description/ 描述 小偷又发现了一个新的可行窃的地区。这个地区只有一个入口&#xff0c;我们称之为 root除了 root 之外&#xff0c;每栋房子有且只有一个“父“房子与之相连一番侦察之后&#xff0c;聪明的小…

chatwoot 开源客服系统搭建

1. 准备开源客服系统&#xff08;我是用的Chatwoot &#xff09; 可以选择以下开源客服系统作为基础&#xff1a; Chatwoot: 功能强大&#xff0c;支持多渠道客户对接&#xff0c;&#xff08;支持app&#xff0c;web&#xff09;。Zammad: 现代的开源工单系统。FreeScout: 免…

sentinel-请求限流、线程隔离、本地回调、熔断

请求限流&#xff1a;控制QPS来达到限流的目的 线程隔离&#xff1a;控制线程数量来达到限流的目录 本地回调&#xff1a;当线程被限流、隔离、熔断之后、就不会发起远程调用、而是使用本地已经准备好的回调去提醒用户 服务熔断&#xff1a;熔断也叫断路器&#xff0c;当失败、…

鸿蒙开发-ArkTS中使用Path组件

在ArkTS中使用Path组件&#xff0c;可以按照以下步骤进行&#xff1a; 一、了解Path组件 Path组件用于根据绘制路径生成封闭的自定义形状。该组件从API Version 7开始支持&#xff0c;并随着后续版本的更新可能增加新的功能。Path组件支持多种属性和方法&#xff0c;用于定义…

高效管理 Nginx 的利器:nginxWebUI 指南和 Docker 部署安装过程

前言 Nginx WebUI 是一个为 Nginx 提供图形化管理界面的工具。通过 WebUI&#xff0c;用户可以轻松管理 Nginx 配置&#xff0c;而无需直接编辑配置文件&#xff0c;尤其适合新手用户和频繁修改配置的场景。 官网文档&#xff1a;nginxWebUI - 文档 本文将分享为什么选择 ngin…

Linux网络 | 理解Web路径 以及 实现一个简单的helloworld网页

前言&#xff1a;本节内容承接上节课的http相关的概念&#xff0c; 主要是实现一个简单的接收http协议请求的服务。这个程序对于我们理解后面的http协议的格式&#xff0c;报头以及网络上的资源的理解&#xff0c; 以及本节web路径等等都有着重要作用。 可以说我们就用代码来理…

2.5万字 - 用TensorFlow和PyTorch分别实现五种经典模型

在深度学习领域&#xff0c;TensorFlow和PyTorch是两大广泛使用的框架&#xff0c;各有其独特的特性和优势。随着人工智能技术的快速发展&#xff0c;越来越多的开发者需要熟练掌握这两种工具&#xff0c;以便在实际项目中选择适合的框架进行高效开发。 目录 入门友好介绍 Te…

【C++】2029:【例4.15】水仙花数

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述&#x1f4af;我的做法思路分析优势不足之处 &#x1f4af;老师的做法思路分析优势不足 &#x1f4af;对比和优化实现方式对比优化思路和操作1. 直接分解数字的各位…

结合长短期记忆网络(LSTM)和无迹卡尔曼滤波器(UKF)的技术在机器人导航和状态估计中的应用前景

结合长短期记忆网络(LSTM)和无迹卡尔曼滤波器(UKF)的技术在机器人导航和状态估计中具有广泛的应用前景。如有滤波、导航方面的代码定制需求,可通过文末卡片联系作者获得帮助 文章目录 结合LSTM和UKF的背景结合LSTM和UKF的优势应用实例研究现状MATLAB代码示例结论结合LSTM和…

Android14 CTS-R6和GTS-12-R2不能同时测试的解决方法

背景 Android14 CTS r6和GTS 12-r1之后&#xff0c;tf-console默认会带起OLC Server&#xff0c;看起来olc server可能是想适配ATS(android-test-station)&#xff0c;一种网页版可视化、可配置的跑XTS的方式。这种网页版ATS对测试人员是比较友好的&#xff0c;网页上简单配置下…

告别Kibana:Elasticsearch 桌面客户端的新变革

告别Kibana&#xff1a;Elasticsearch 桌面客户端的新变革 在大数据处理与分析领域&#xff0c;Elasticsearch 及其相关技术的应用日益广泛。长期以来&#xff0c;Kibana 在数据可视化与查询管理方面占据重要地位&#xff0c;但随着技术的不断发展&#xff0c;用户对于更高效、…

HTML5实现喜庆的新年快乐网页源码

HTML5实现喜庆的新年快乐网页源码 前言一、设计来源1.1 主界面1.2 关于新年界面1.3 新年庆祝活动界面1.4 新年活动组织界面1.5 新年祝福订阅界面1.6 联系我们界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 HTML5实现喜庆的新年快乐网页源码&#xff0c;春节新年网…

【广州计算机学会、广州互联网协会联合主办 | ACM独立出版 | 高录用】第四届大数据、信息与计算机网络国际学术会议(BDICN 2025)

第四届大数据、信息与计算机网络国际学术会议&#xff08;BDICN 2025&#xff09;定于2025年01月10-12日在中国广州举行。会议旨在为从事“大数据”、“计算机网络”与“信息”研究的专家学者、工程技术人员、技术研发人员提供一个共享科研成果和前沿技术&#xff0c;了解学术发…

C语言函数栈帧的创建和销毁

文章目录 一、寄存器二、函数栈帧的创建和销毁1.什么是函数栈帧&#xff1f;2.案例代码-讲解3.总结函数栈帧 一、寄存器 寄存器(Register)是中央处理机、主存储器和其他数字设备中某些特定用途的存储单元。寄存器是集成电路中非常重要的一种存储单元&#xff1b;其可用来暂存指…

我的博客年度之旅:感恩、成长与展望

目录 感恩有你 技能满点 新年新征程 嘿&#xff0c;各位技术大佬、数码潮咖还有屏幕前超爱学习的小伙伴们&#xff01;当新年的钟声即将敲响&#xff0c;我们站在时光的交汇点上&#xff0c;回首过往&#xff0c;满心感慨&#xff1b;展望未来&#xff0c;豪情满怀。过去的这…

【数据库初阶】MySQL数据类型

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; 数据库初阶 &#x1f389;其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 亲爱的小伙伴们&#xff0c;大家好&#xff01;在这篇文章中&#xff0c;我们将深入浅出地为大家讲解 MySQL…

webrtc 源码阅读 make_ref_counted模板函数用法

目录 1. 模板参数解析 1.1 typename T 1.2 typename... Args 1.3 typename std::enable_if::value, T>::type* nullptr 2. scoped_refptr 3. new RefCountedObject(std::forward(args)...); 4. 综合说明 5.在webrtc中的用法 5.1 peerConnectionFactory对象的构建过…