jQuery 3D自由立体旋转js特效代码

版权:原创 更新时间:1年以上
[该文章底部包含文件资源,可根据自己情况,决定是否下载资源使用,时间>金钱,如有需要,立即查看资源]

以下是 jQuery 3D自由立体旋转js特效代码 的示例演示效果:

当前平台(PC电脑)
  • 平台:

部分效果截图:

jQuery 3D自由立体旋转js特效代码

HTML代码(index.html):

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>3D自由立体旋转</title>
    <style>
        body {
            background-color: #ffffff;
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>
    <script type="text/javascript" src="js/three.min.js"></script>
    <script type="text/javascript" src="js/TrackballControls.js"></script>
    <script type="text/javascript" src="js/CSS3DRenderer.js"></script>
    <script>

        var camera, scene, renderer;
        var geometry, material, mesh;

        var scene2, renderer2;

        var controls;

        init();
        animate();

        function init() {

            camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
            camera.position.set(500, 100, 100);

            controls = new THREE.TrackballControls(camera);

            controls.rotateSpeed = 1.0;
            controls.zoomSpeed = 1.2;
            controls.panSpeed = 0.8;

            controls.noZoom = false;
            controls.noPan = false;

            controls.staticMoving = false;
            controls.dynamicDampingFactor = 0.3;

            controls.keys = [70, 90, 75];

            scene = new THREE.Scene();

            geometry = new THREE.CubeGeometry(200, 200, 200);
            material = new THREE.MeshBasicMaterial({ color: 0x000000, wireframe: true, wireframeLinewidth: 1 });

            mesh = new THREE.Mesh(geometry, material);
            scene.add(mesh);

            renderer = new THREE.CanvasRenderer();
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);

            //

            scene2 = new THREE.Scene();

            for (var i = 0; i < 20; i++) {

                var element = document.createElement('div');
                element.style.width = '100px';
                element.style.height = '100px';
                element.style.background = new THREE.Color(Math.random() * 0xffffff).getStyle();

                var object = new THREE.CSS3DObject(element);
                object.position.x = Math.random() * 200 - 100;
                object.position.y = Math.random() * 200 - 100;
                object.position.z = Math.random() * 200 - 100;
                object.scale.x = Math.random() + 0.5;
                object.scale.y = Math.random() + 0.5;
                scene2.add(object);

            }

            //

            renderer2 = new THREE.CSS3DRenderer();
            renderer2.setSize(window.innerWidth, window.innerHeight);
            renderer2.domElement.style.position = 'absolute';
            renderer2.domElement.style.top = 0;
            document.body.appendChild(renderer2.domElement);

        }

        function animate() {

            requestAnimationFrame(animate);

            controls.update();

            renderer.render(scene, camera);
            renderer2.render(scene2, camera);

        }

    </script>
    <br><br><br><br><br><br><br><br><br><br>
    <br><br><br><br><br><br><br><br><br><br>
</body>
</html>

JS代码(CSS3DRenderer.js):

/** * Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs * @author mrdoob / http://mrdoob.com/ */
THREE.CSS3DObject = function ( element ){
	THREE.Object3D.call( this );
	this.element = element;
	this.element.style.position = "absolute";
	this.element.style.WebkitTransformStyle = 'preserve-3d';
	this.element.style.MozTransformStyle = 'preserve-3d';
	this.element.style.oTransformStyle = 'preserve-3d';
	this.element.style.transformStyle = 'preserve-3d';
}
;
	THREE.CSS3DObject.prototype = Object.create( THREE.Object3D.prototype );
	THREE.CSS3DSprite = function ( element ){
	THREE.CSS3DObject.call( this,element );
}
;
	THREE.CSS3DSprite.prototype = Object.create( THREE.CSS3DObject.prototype );
	//THREE.CSS3DRenderer = function (){
	console.log( 'THREE.CSS3DRenderer',THREE.REVISION );
	var _width,_height;
	var _widthHalf,_heightHalf;
	var _projector = new THREE.Projector();
	var _tmpMatrix = new THREE.Matrix4();
	this.domElement = document.createElement( 'div' );
	this.domElement.style.overflow = 'hidden';
	this.domElement.style.WebkitTransformStyle = 'preserve-3d';
	this.domElement.style.WebkitPerspectiveOrigin = '50% 50%';
	this.domElement.style.MozTransformStyle = 'preserve-3d';
	this.domElement.style.MozPerspectiveOrigin = '50% 50%';
	this.domElement.style.oTransformStyle = 'preserve-3d';
	this.domElement.style.oPerspectiveOrigin = '50% 50%';
	this.domElement.style.transformStyle = 'preserve-3d';
	this.domElement.style.perspectiveOrigin = '50% 50%';
	// TODO:Shouldn't it be possible to remove cameraElement?this.cameraElement = document.createElement( 'div' );
	this.cameraElement.style.WebkitTransformStyle = 'preserve-3d';
	this.cameraElement.style.MozTransformStyle = 'preserve-3d';
	this.cameraElement.style.oTransformStyle = 'preserve-3d';
	this.cameraElement.style.transformStyle = 'preserve-3d';
	this.domElement.appendChild( this.cameraElement );
	this.setSize = function ( width,height ){
	_width = width;
	_height = height;
	_widthHalf = _width / 2;
	_heightHalf = _height / 2;
	this.domElement.style.width = width + 'px';
	this.domElement.style.height = height + 'px';
	this.cameraElement.style.width = width + 'px';
	this.cameraElement.style.height = height + 'px';
}
;
	var epsilon = function ( value ){
	return Math.abs( value ) < 0.000001 ? 0:value;
}
;
	var getCameraCSSMatrix = function ( matrix ){
	var elements = matrix.elements;
	return 'matrix3d(' +epsilon( elements[ 0 ] ) + ',' +epsilon( - elements[ 1 ] ) + ',' +epsilon( elements[ 2 ] ) + ',' +epsilon( elements[ 3 ] ) + ',' +epsilon( elements[ 4 ] ) + ',' +epsilon( - elements[ 5 ] ) + ',' +epsilon( elements[ 6 ] ) + ',' +epsilon( elements[ 7 ] ) + ',' +epsilon( elements[ 8 ] ) + ',' +epsilon( - elements[ 9 ] ) + ',' +epsilon( elements[ 10 ] ) + ',' +epsilon( elements[ 11 ] ) + ',' +epsilon( elements[ 12 ] ) + ',' +epsilon( - elements[ 13 ] ) + ',' +epsilon( elements[ 14 ] ) + ',' +epsilon( elements[ 15 ] ) +')';
}
var getObjectCSSMatrix = function ( matrix ){
	var elements = matrix.elements;
	return 'translate3d(-50%,-50%,0) matrix3d(' +epsilon( elements[ 0 ] ) + ',' +epsilon( elements[ 1 ] ) + ',' +epsilon( elements[ 2 ] ) + ',' +epsilon( elements[ 3 ] ) + ',' +epsilon( - elements[ 4 ] ) + ',' +epsilon( - elements[ 5 ] ) + ',' +epsilon( - elements[ 6 ] ) + ',' +epsilon( - elements[ 7 ] ) + ',' +epsilon( elements[ 8 ] ) + ',' +epsilon( elements[ 9 ] ) + ',' +epsilon( elements[ 10 ] ) + ',' +epsilon( elements[ 11 ] ) + ',' +epsilon( elements[ 12 ] ) + ',' +epsilon( elements[ 13 ] ) + ',' +epsilon( elements[ 14 ] ) + ',' +epsilon( elements[ 15 ] ) +')';
}
this.render = function ( scene,camera ){
	var fov = 0.5 / Math.tan( THREE.Math.degToRad( camera.fov * 0.5 ) ) * _height;
	this.domElement.style.WebkitPerspective = fov + "px";
	this.domElement.style.MozPerspective = fov + "px";
	this.domElement.style.oPerspective = fov + "px";
	this.domElement.style.perspective = fov + "px";
	var objects = _projector.projectScene( scene,camera,false ).objects;
	var style = "translate3d(0,0," + fov + "px)" + getCameraCSSMatrix( camera.matrixWorldInverse ) + " translate3d(" + _widthHalf + "px," + _heightHalf + "px,0)";
	this.cameraElement.style.WebkitTransform = style;
	this.cameraElement.style.MozTransform = style;
	this.cameraElement.style.oTransform = style;
	this.cameraElement.style.transform = style;
	for ( var i = 0,il = objects.length;
	i < il;
	i ++ ){
	var object = objects[ i ].object;
	if ( object instanceof THREE.CSS3DObject ){
	var element = object.element;
	if ( object instanceof THREE.CSS3DSprite ){
	// http://swiftcoder.wordpress.com/2008/11/25/constructing-a-billboard-matrix/_tmpMatrix.copy( camera.matrixWorldInverse );
	_tmpMatrix.transpose();
	_tmpMatrix.extractPosition( object.matrixWorld );
	_tmpMatrix.scale( object.scale );
	_tmpMatrix.elements[ 3 ] = 0;
	_tmpMatrix.elements[ 7 ] = 0;
	_tmpMatrix.elements[ 11 ] = 0;
	_tmpMatrix.elements[ 15 ] = 1;
	style = getObjectCSSMatrix( _tmpMatrix );
}
else{
	style = getObjectCSSMatrix( object.matrixWorld );
}
/*element.style.WebkitBackfaceVisibility = 'hidden';
	element.style.MozBackfaceVisibility = 'hidden';
	element.style.oBackfaceVisibility = 'hidden';
	element.style.backfaceVisibility = 'hidden';
	*/
element.style.WebkitTransform = style;
	element.style.MozTransform = style;
	element.style.oTransform = style;
	element.style.transform = style;
	if ( element.parentNode !== this.cameraElement ){
	this.cameraElement.appendChild( element );
}
}
}
}
;
}
;
	

JS代码(TrackballControls.js):

/** * @author Eberhard Graether / http://egraether.com/ */
THREE.TrackballControls = function ( object,domElement ){
	THREE.EventDispatcher.call( this );
	var _this = this;
	var STATE ={
	NONE:-1,ROTATE:0,ZOOM:1,PAN:2,TOUCH_ROTATE:3,TOUCH_ZOOM:4,TOUCH_PAN:5}
;
	this.object = object;
	this.domElement = ( domElement !== undefined ) ? domElement:document;
	// APIthis.enabled = true;
	this.screen ={
	width:0,height:0,offsetLeft:0,offsetTop:0}
;
	this.radius = ( this.screen.width + this.screen.height ) / 4;
	this.rotateSpeed = 1.0;
	this.zoomSpeed = 1.2;
	this.panSpeed = 0.3;
	this.noRotate = false;
	this.noZoom = false;
	this.noPan = false;
	this.staticMoving = false;
	this.dynamicDampingFactor = 0.2;
	this.minDistance = 0;
	this.maxDistance = Infinity;
	this.keys = [ 65 /*A*/
,83 /*S*/
,68 /*D*/
 ];
	// internalsthis.target = new THREE.Vector3();
	var lastPosition = new THREE.Vector3();
	var _state = STATE.NONE,_prevState = STATE.NONE,_eye = new THREE.Vector3(),_rotateStart = new THREE.Vector3(),_rotateEnd = new THREE.Vector3(),_zoomStart = new THREE.Vector2(),_zoomEnd = new THREE.Vector2(),_touchZoomDistanceStart = 0,_touchZoomDistanceEnd = 0,_panStart = new THREE.Vector2(),_panEnd = new THREE.Vector2();
	// for resetthis.target0 = this.target.clone();
	this.position0 = this.object.position.clone();
	this.up0 = this.object.up.clone();
	// eventsvar changeEvent ={
	type:'change'}
;
	// methodsthis.handleResize = function (){
	this.screen.width = window.innerWidth;
	this.screen.height = window.innerHeight;
	this.screen.offsetLeft = 0;
	this.screen.offsetTop = 0;
	this.radius = ( this.screen.width + this.screen.height ) / 4;
}
;
	this.handleEvent = function ( event ){
	if ( typeof this[ event.type ] == 'function' ){
	this[ event.type ]( event );
}
}
;
	this.getMouseOnScreen = function ( clientX,clientY ){
	return new THREE.Vector2(( clientX - _this.screen.offsetLeft ) / _this.radius * 0.5,( clientY - _this.screen.offsetTop ) / _this.radius * 0.5);
}
;
	this.getMouseProjectionOnBall = function ( clientX,clientY ){
	var mouseOnBall = new THREE.Vector3(( clientX - _this.screen.width * 0.5 - _this.screen.offsetLeft ) / _this.radius,( _this.screen.height * 0.5 + _this.screen.offsetTop - clientY ) / _this.radius,0.0);
	var length = mouseOnBall.length();
	if ( length > 1.0 ){
	mouseOnBall.normalize();
}
else{
	mouseOnBall.z = Math.sqrt( 1.0 - length * length );
}
_eye.copy( _this.object.position ).sub( _this.target );
	var projection = _this.object.up.clone().setLength( mouseOnBall.y );
	projection.add( _this.object.up.clone().cross( _eye ).setLength( mouseOnBall.x ) );
	projection.add( _eye.setLength( mouseOnBall.z ) );
	return projection;
}
;
	this.rotateCamera = function (){
	var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
	if ( angle ){
	var axis = ( new THREE.Vector3() ).crossVectors( _rotateStart,_rotateEnd ).normalize(),quaternion = new THREE.Quaternion();
	angle *= _this.rotateSpeed;
	quaternion.setFromAxisAngle( axis,-angle );
	_eye.applyQuaternion( quaternion );
	_this.object.up.applyQuaternion( quaternion );
	_rotateEnd.applyQuaternion( quaternion );
	if ( _this.staticMoving ){
	_rotateStart.copy( _rotateEnd );
}
else{
	quaternion.setFromAxisAngle( axis,angle * ( _this.dynamicDampingFactor - 1.0 ) );
	_rotateStart.applyQuaternion( quaternion );
}
}
}
;
	this.zoomCamera = function (){
	if ( _state === STATE.TOUCH_ZOOM ){
	var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
	_touchZoomDistanceStart = _touchZoomDistanceEnd;
	_eye.multiplyScalar( factor );
}
else{
	var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
	if ( factor !== 1.0 && factor > 0.0 ){
	_eye.multiplyScalar( factor );
	if ( _this.staticMoving ){
	_zoomStart.copy( _zoomEnd );
}
else{
	_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
}
}
}
}
;
	this.panCamera = function (){
	var mouseChange = _panEnd.clone().sub( _panStart );
	if ( mouseChange.lengthSq() ){
	mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
	var pan = _eye.clone().cross( _this.object.up ).setLength( mouseChange.x );
	pan.add( _this.object.up.clone().setLength( mouseChange.y ) );
	_this.object.position.add( pan );
	_this.target.add( pan );
	if ( _this.staticMoving ){
	_panStart = _panEnd;
}
else{
	_panStart.add( mouseChange.subVectors( _panEnd,_panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
}
}
}
;
	this.checkDistances = function (){
	if ( !_this.noZoom || !_this.noPan ){
	if ( _this.object.position.lengthSq() > _this.maxDistance * _this.maxDistance ){
	_this.object.position.setLength( _this.maxDistance );
}
if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ){
	_this.object.position.addVectors( _this.target,_eye.setLength( _this.minDistance ) );
}
}
}
;
	this.update = function (){
	_eye.subVectors( _this.object.position,_this.target );
	if ( !_this.noRotate ){
	_this.rotateCamera();
}
if ( !_this.noZoom ){
	_this.zoomCamera();
}
if ( !_this.noPan ){
	_this.panCamera();
}
_this.object.position.addVectors( _this.target,_eye );
	_this.checkDistances();
	_this.object.lookAt( _this.target );
	if ( lastPosition.distanceToSquared( _this.object.position ) > 0 ){
	_this.dispatchEvent( changeEvent );
	lastPosition.copy( _this.object.position );
}
}
;
	this.reset = function (){
	_state = STATE.NONE;
	_prevState = STATE.NONE;
	_this.target.copy( _this.target0 );
	_this.object.position.copy( _this.position0 );
	_this.object.up.copy( _this.up0 );
	_eye.subVectors( _this.object.position,_this.target );
	_this.object.lookAt( _this.target );
	_this.dispatchEvent( changeEvent );
	lastPosition.copy( _this.object.position );
}
;
	// listenersfunction keydown( event ){
	if ( _this.enabled === false ) return;
	window.removeEventListener( 'keydown',keydown );
	_prevState = _state;
	if ( _state !== STATE.NONE ){
	return;
}
else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ){
	_state = STATE.ROTATE;
}
else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ){
	_state = STATE.ZOOM;
}
else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ){
	_state = STATE.PAN;
}
}
function keyup( event ){
	if ( _this.enabled === false ) return;
	_state = _prevState;
	window.addEventListener( 'keydown',keydown,false );
}
function mousedown( event ){
	if ( _this.enabled === false ) return;
	event.preventDefault();
	event.stopPropagation();
	if ( _state === STATE.NONE ){
	_state = event.button;
}
if ( _state === STATE.ROTATE && !_this.noRotate ){
	_rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.clientX,event.clientY );
}
else if ( _state === STATE.ZOOM && !_this.noZoom ){
	_zoomStart = _zoomEnd = _this.getMouseOnScreen( event.clientX,event.clientY );
}
else if ( _state === STATE.PAN && !_this.noPan ){
	_panStart = _panEnd = _this.getMouseOnScreen( event.clientX,event.clientY );
}
document.addEventListener( 'mousemove',mousemove,false );
	document.addEventListener( 'mouseup',mouseup,false );
}
function mousemove( event ){
	if ( _this.enabled === false ) return;
	event.preventDefault();
	event.stopPropagation();
	if ( _state === STATE.ROTATE && !_this.noRotate ){
	_rotateEnd = _this.getMouseProjectionOnBall( event.clientX,event.clientY );
}
else if ( _state === STATE.ZOOM && !_this.noZoom ){
	_zoomEnd = _this.getMouseOnScreen( event.clientX,event.clientY );
}
else if ( _state === STATE.PAN && !_this.noPan ){
	_panEnd = _this.getMouseOnScreen( event.clientX,event.clientY );
}
}
function mouseup( event ){
	if ( _this.enabled === false ) return;
	event.preventDefault();
	event.stopPropagation();
	_state = STATE.NONE;
	document.removeEventListener( 'mousemove',mousemove );
	document.removeEventListener( 'mouseup',mouseup );
}
function mousewheel( event ){
	if ( _this.enabled === false ) return;
	event.preventDefault();
	event.stopPropagation();
	var delta = 0;
	if ( event.wheelDelta ){
	// WebKit / Opera / Explorer 9delta = event.wheelDelta / 40;
}
else if ( event.detail ){
	// Firefoxdelta = - event.detail / 3;
}
_zoomStart.y += ( 1 / delta ) * 0.05;
}
function touchstart( event ){
	if ( _this.enabled === false ) return;
	switch ( event.touches.length ){
	case 1:_state = STATE.TOUCH_ROTATE;
	_rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX,event.touches[ 0 ].pageY );
	break;
	case 2:_state = STATE.TOUCH_ZOOM;
	var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
	var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
	_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
	break;
	case 3:_state = STATE.TOUCH_PAN;
	_panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX,event.touches[ 0 ].pageY );
	break;
	default:_state = STATE.NONE;
}
}
function touchmove( event ){
	if ( _this.enabled === false ) return;
	event.preventDefault();
	event.stopPropagation();
	switch ( event.touches.length ){
	case 1:_rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX,event.touches[ 0 ].pageY );
	break;
	case 2:var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
	var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
	_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy )break;
	case 3:_panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX,event.touches[ 0 ].pageY );
	break;
	default:_state = STATE.NONE;
}
}
function touchend( event ){
	if ( _this.enabled === false ) return;
	switch ( event.touches.length ){
	case 1:_rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX,event.touches[ 0 ].pageY );
	break;
	case 2:_touchZoomDistanceStart = _touchZoomDistanceEnd = 0;
	break;
	case 3:_panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX,event.touches[ 0 ].pageY );
	break;
}
_state = STATE.NONE;
}
this.domElement.addEventListener( 'contextmenu',function ( event ){
	event.preventDefault();
}
,false );
	this.domElement.addEventListener( 'mousedown',mousedown,false );
	this.domElement.addEventListener( 'mousewheel',mousewheel,false );
	this.domElement.addEventListener( 'DOMMouseScroll',mousewheel,false );
	// firefoxthis.domElement.addEventListener( 'touchstart',touchstart,false );
	this.domElement.addEventListener( 'touchend',touchend,false );
	this.domElement.addEventListener( 'touchmove',touchmove,false );
	window.addEventListener( 'keydown',keydown,false );
	window.addEventListener( 'keyup',keyup,false );
	this.handleResize();
}
;
	
附件:下载该文件资源,减少时间成本(增值服务)
留言
该资源可下载
File Source
.rar
90.67 KB
jquery特效3
最新结算
jquery虚拟键盘中文打字效果js代码
类型: .rar 金额: CNY 2.31¥ 状态: 待结算 详细>
jquery虚拟键盘中文打字效果js代码
类型: .rar 金额: CNY 0.29¥ 状态: 待结算 详细>
HTML5实现CSS滤镜图片切换特效代码
类型: .rar 金额: CNY 2.31¥ 状态: 待结算 详细>
jQuery头像裁剪插件cropbox js代码
类型: .rar 金额: CNY 0.29¥ 状态: 待结算 详细>
jQuery头像裁剪插件cropbox js代码
类型: .rar 金额: CNY 2.31¥ 状态: 待结算 详细>
CSS3制作3D图片立方体旋转特效
类型: .rar 金额: CNY 2.31¥ 状态: 待结算 详细>
CSS3制作3D图片立方体旋转特效
类型: .rar 金额: CNY 0.29¥ 状态: 待结算 详细>
CSS3制作3D图片立方体旋转特效
类型: .rar 金额: CNY 2.31¥ 状态: 待结算 详细>
CSS3制作3D图片立方体旋转特效
类型: .rar 金额: CNY 0.29¥ 状态: 待结算 详细>
jQuery+css3实现信封效果
类型: .rar 金额: CNY 0.29¥ 状态: 待结算 详细>
我们力求给您提供有用的文章,再此基础上,会附加营收资源,不做任何广告,让平台可以更好发展 若您发现您的权利被侵害,或使用了您的版权,请发邮件联系 sunlifel@foxmail.com ggbig觉得 : 不提供源码的文章不是好文章
合作伙伴
联系我们
  • QQ:21499807
  • 邮箱:sunlifel@foxmail.com
  • QQ扫一扫加QQ
    QQ扫一扫
Copyright 2023-2024 ggbig.com·皖ICP备2023004211号-1
打赏文章