精华内容
下载资源
问答
  • 如图所示,导航栏随列表滑动而动态改变背景色和标题显隐,这种交互设计比较常见,那该怎么去实现这样的交互效果呢?想必大体的思路大家都想得到,首先是让VC的view的布局从屏幕上边缘开始,在UITableView滚动回调...

     

    | 导语 套路,在武术中是指一连串含有技击和攻防含义的动作组合,在本文中,指的就是一套实现特定功能的代码组合。

    一、交互效果

    如图所示,导航栏随列表滑动而动态改变背景色和标题显隐,这种交互设计比较常见,那该怎么去实现这样的交互效果呢?想必大体的思路大家都能想得到,首先是让VC的view的布局从屏幕上边缘开始,在UITableView滚动回调方法中根据偏移量改变导航栏的背景透明度。思路简单,但是具体到实现却是有不少技术细节要注意。下面我将分享我所在iOS项目实现导航栏动态变化交互效果的套路。

    二、代码套路

    第一步,如何让view的布局从屏幕顶部边缘开始,到TabBar的顶部截止?

    iOS 7 之后,UINavigationBar和UITabBar默认都变成了半透明,系统也调整了view的布局,默认使用全屏布局(full-screen layout),即铺满整个屏幕。为了让开发者可以自主控制view的布局,UIViewController新增了edgesForExtendedLayout属性,通过设置此属性,你可以指定view的边(上、下、左、右)延伸到整屏幕。

    @property(nonatomic,assign) UIRectEdge edgesForExtendedLayout NS_AVAILABLE_IOS(7_0);
    
    typedef NS_OPTIONS(NSUInteger, UIRectEdge) {
    
    UIRectEdgeNone = 0,
    
    UIRectEdgeTop = 1 << 0,
    
    UIRectEdgeLeft = 1 << 1,
    
    UIRectEdgeBottom = 1 << 2,
    
    UIRectEdgeRight = 1 << 3,
    
    UIRectEdgeAll = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight
    
    } NS_ENUM_AVAILABLE_IOS(7_0);

    刚刚说到UINavigationBar和UITabBar默认是半透明,但如果是不透明,你会发现设置edgesForExtendedLayout没有效果,如何在不透明的情况下也能延伸到整屏幕呢。UIViewController同时新增了一个extendedLayoutIncludesOpaqueBarssh属性,默认是NO,如果设置为YES,则在Bar不透明的情况下,edgesForExtendedLayout也能生效。所以套路的第一步是:

    self.edgesForExtendedLayout = UIRectEdgeTop;
    self.extendedLayoutIncludesOpaqueBars = YES;

    第二步,如何动态改变导航栏的透明度和标题?

    UINavigationBar的translucent、barTintColor、backgroundImage三者共同决定了UINavigationBar的背景效果,而translucent在中间起非常关键的作用,它决定了系统如何使用barTintColor和backgroundImage去设置UINavigationBar的背景效果。如果不了解其中细节的,强烈推荐我的另一篇文章《UINavigationBar的translucent、barTintColor、backgroundImage》下面直接分享动态改变导航栏的透明度和标题的最佳实践写法:

    1. 不主动去设置UINavigationBar的translucent为YES,因为如果主动设置为YES,则导航栏无法做到完全不透明;

    2. 通过setBackgroundImage:forBarMetrics: 的方式来设置导航栏背景,以达到控制背景效果的目的,为什么要怎样操作,在我刚刚推荐的文章里有详细的分析;

    3. backgroundImage通过颜色生成,通过改变颜色alpha值,来动态控制图片的透明度,最终控制导航栏透明度;

    4. 如果导航栏已经是不透明的背景了,就不需要再重复设置,减少颜色转图片的资源消耗,可以通过translucent的值是否为NO来判断是否已经设为不透明背景;

    5. 通过设置self.navigationItem.titlel来控制标题的变化,而不是self.title, 因为self.title会同时改变tabBar是的title;

    所以套路的第二步是:

    // 根据scrollView的偏移量来动态计算alpha值
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        CGPoint offset = scrollView.contentOffset;
        CGFloat alpha = 1.0;
        if (offset.y <= 0) {
            alpha = 0;
        } else if (offset.y < TOP_SAFE_OFFSET) {
            alpha = 1.0 - (TOP_SAFE_OFFSET - offset.y)/TOP_SAFE_OFFSET;
        } else {
            alpha = 1.0;
        }
        if (!(alpha == 1 && !self.navigationController.navigationBar.translucent)) {
            //如果导航栏背景已经是不透明,那就不再需要重复设置了,减少颜色转图片的开销
            [self.navigationController.navigationBar ig_setBackgroundImageByColor:HEXACOLOR(IGAME_NAVIBAR_COLOUR_VALUE, alpha) forBarMetrics:UIBarMetricsDefault];
        }
        self.navigationItem.title = alpha > 0.2 ? @"赛事":@"";
    }

    项目中导航栏一般是纯色背景,所以提供一个分类方法,快速通过颜色来设置背景图

    @interface UINavigationBar (IGAppearance)
    
    - (void)ig_setBackgroundImageByColor:(UIColor *)imageColor forBarMetrics:(UIBarMetrics)barMetrics;
    
    @end

    通过颜色来创建图片的方法

    @interface UIImage (IGUIKit)
    
    + (nullable UIImage *)imageWithColor:(UIColor *)color;
    
    @end

    第三步,如何让tableView不自动偏移?

    如图,当我们设置了view从顶部边缘开始布局之后,发现tableView会自动偏移,使内容从导航栏底部开始,为什么会发生偏移呢? 因为tableview从屏幕顶部开始布局,为了不让导航栏遮住tableView的内容,系统默认会自动调整tableview的contentInset,我们可以打印一下tableView,可以看到一个adjustedContentInset: {64, 0, 0, 0}。adjustedContentInset是iOS 11之后新增的属性。如果是iOS 11之前,那就是调整contentInset。

    <UITableView: 0x1049d2200; frame = (0 0; 375 618); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x2836147b0>; layer = <CALayer: 0x283805f20>;
    
    contentOffset: {0, -62}; contentSize: {375, 2068}; adjustedContentInset: {64, 0, 0, 0}>
    
    (lldb) po NSStringFromUIEdgeInsets(self.tableView.contentInset)
    
    {64, 0, 0, 0}

    那如何禁止系统自动调整tableView的contentInset呢?下面就是我们套路的最后一步:

    if (@available(iOS 11.0, *)) {
        self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    } else {
        self.automaticallyAdjustsScrollViewInsets = NO;
    }

     

    通过以上三个步骤,我们便能轻轻松松实现导航栏动态变化交互效果。感谢大家的阅读,欢迎大家提出问题和建议!

    展开全文
  • 用SVG实现动态交互式地图

    千次阅读 2017-06-04 17:46:11
    SVG可以实现无损缩放,在性能上要比其它格式的图片更好,今天教大家用SVG实现一个动态交互式地图,先上效果图: 一、 实现思路 下载含有台湾地图的SVG,地图资源可以在这个网站上https://www.am

    用SVG实现动态交互式地图

    SVG是目前最火热的图像文件格式,它的英文全称为Scalable Vector Graphics,意思为可缩放的矢量图形,它是基于XML,由W3C联盟进行开发。SVG可以实现无损缩放,在性能上要比其它格式的图片更好,今天教大家用SVG实现一个动态交互式地图,先上效果图:
    这里写图片描述
    一、 实现思路
    下载含有台湾地图的SVG,地图资源可以在这个网站上https://www.amcharts.com/dl/javascript-maps/ 下载,
    http://inloop.github.io/svg2android/ 网站将SVG资源转换成相应的Android代码,利用DOM解析SVG的代码,将属性pathData数据封装成JavaBean,最重要的是得到点击的Path。Path指令解析如下所示:

    • M = moveto(M X,Y) :将画笔移动到指定的坐标位置,相当于 android Path 里的moveTo()
    • L = lineto(L X,Y) :画直线到指定的坐标位置,相当于 android Path 里的lineTo()
    • H = horizontal lineto(H X):画水平线到指定的X坐标位置
    • V = vertical lineto(V Y):画垂直线到指定的Y坐标位置
    • C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三次贝赛曲线
    • S = smooth curveto(S X2,Y2,ENDX,ENDY) 同样三次贝塞尔曲线,更平滑
    • Q = quadratic Belzier curve(Q X,Y,ENDX,ENDY):二次贝赛曲线
    • T = smooth quadratic Belzier curveto(T ENDX,ENDY):映射 同样二次贝塞尔曲线,更平滑
    • A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y):弧线 ,相当于arcTo()
    • Z = closepath():关闭路径(会自动绘制链接起点和终点)

    重写onDraw方法,利用path绘制台湾地图,重写onTouchEvent方法,记录手指触摸位置,判断坐标是否在某一个市的范围内。
    二、 代码实例
    自定义TaiWanMapView

    public class TaiWanMapView extends View {
        private static final String TAG = TaiWanMapView.class.getName();
        private List<TaiWanItem> taiwanItems = new ArrayList<TaiWanItem>();
        //被点击的区域
        private TaiWanItem selectItem;
        //缩放1.3倍
        private float scale = 1.3f;
        private Context mContext;
        private Paint mPaint;
        private int[] colors = new int[]{0xFF239BD7,0xFF30A9E5,0xFF80CBF1,0xFFF0E68C};
        GestureDetectorCompat gestureDetectorCompat;
    
        public TaiWanMapView(Context context) {
            super(context);
        }
    
        public TaiWanMapView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
        private void init(Context context) {
            mContext = context;
            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            gestureDetectorCompat = new GestureDetectorCompat(context,new GestureDetector.SimpleOnGestureListener(){
                @Override
                public boolean onDown(MotionEvent e) {
                    Log.d(TAG,"onDown x:"+e.getX()+";y:"+e.getY());
                    handleTouch(e.getX(),e.getY());
                    return true;
                }
            });
            thread.start();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.save();
            //将画布缩放1.3倍
            canvas.scale(scale,scale);
            if(taiwanItems != null){
                for(TaiWanItem item:taiwanItems){
                    if(item != selectItem){
                        item.draw(canvas,mPaint,false);
                    }
                }
                if(selectItem != null){
                    selectItem.draw(canvas,mPaint,true);
                }
            }
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            return gestureDetectorCompat.onTouchEvent(event);
        }
    
        private void handleTouch(float x,float y){
            TaiWanItem taiWanItem = null;
            if(taiwanItems != null){
                for(TaiWanItem item : taiwanItems){
                    if(item.isTouch((int)(x/scale),(int)(y/scale))){
                        taiWanItem = item;
                        break;
                    }
                }
                if(taiWanItem != null) {
                    selectItem = taiWanItem;
                    postInvalidate();
                }
            }
        }
    
        Thread thread = new Thread(){
            @Override
            public void run() {
                InputStream inputStream = mContext.getResources().openRawResource(R.raw.taiwan);
                //采用Dom解析器解析xml
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                DocumentBuilder builder = null;
                try {
                    builder = factory.newDocumentBuilder();
                    Document doc = builder.parse(inputStream);
                    Element rootelement = doc.getDocumentElement();
                    NodeList items = rootelement.getElementsByTagName("path");
                    for(int i=0;i<items.getLength();i++){
                        Element element = (Element) items.item(i);
                        String pathData = element.getAttribute("android:pathData");
                        Path path = PathParser.createPathFromPathData(pathData);
                        TaiWanItem item = new TaiWanItem(path);
                        taiwanItems.add(item);
                    }
                    handler.sendEmptyMessage(1);
                } catch (ParserConfigurationException e) {
                    e.printStackTrace();
                } catch (SAXException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
    
        Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                if(taiwanItems == null || taiwanItems.size()==0)
                    return;
    
                int colorNum = taiwanItems.size();
                int color = Color.WHITE;
                //赋予颜色
                for(int i=0;i<colorNum;i++){
                    int flag = i % 4;
                    switch(flag){
                        case 1:
                            color = colors[0];
                            break;
                        case 2:
                            color = colors[1];
                            break;
                        case 3:
                            color = colors[2];
                            break;
                        default:
                            color = colors[3];
                    }
                    taiwanItems.get(i).setDrawColor(color);
                }
                postInvalidate();
            }
        };
    }

    将地图path封装成TaiWanItem

    public class TaiWanItem {
    
        private Path path;
        private int drawColor;
    
        public TaiWanItem(Path path) {
            this.path = path;
        }
    
        /**
         * 绘制地图path
         * @param canvas
         * @param paint
         * @param isSelect
         */
        public void draw(Canvas canvas, Paint paint,boolean isSelect){
            if(isSelect){
                //画阴影图层
                paint.setStrokeWidth(2);
                paint.setShadowLayer(8,0,0,0xffffff);
                paint.setStyle(Paint.Style.FILL);
                paint.setColor(Color.BLACK);
                canvas.drawPath(path,paint);
                //画区域path
                paint.clearShadowLayer();
                paint.setStrokeWidth(2);
                paint.setStyle(Paint.Style.FILL);
                paint.setColor(drawColor);
                canvas.drawPath(path,paint);
            }else{
                //画线条
                paint.clearShadowLayer();
                paint.setStrokeWidth(1);
                paint.setStyle(Paint.Style.STROKE);
                paint.setColor(0xFFD0E8F4);
                canvas.drawPath(path,paint);
                //画区域
                paint.setStrokeWidth(2);
                paint.setStyle(Paint.Style.FILL);
                paint.setColor(drawColor);
                canvas.drawPath(path,paint);
            }
        }
    
        /**
         * 判断当前点击坐标是否在path范围内
         * @param x
         * @param y
         * @return
         */
        public boolean isTouch(int x,int y){
            RectF rectF = new RectF();
            path.computeBounds(rectF,true);
            Region region = new Region();
            region.setPath(path,new Region((int)rectF.left,(int)rectF.top,(int)rectF.right,(int)rectF.bottom));
    //判断X,Y是否在region区域范围内
            if(region.contains(x,y)) return true;
            return false;
        }
    
        public void setDrawColor(int drawColor) {
            this.drawColor = drawColor;
        }
    }

    整个代码不算很复杂,关键就是在onDraw方法里面,利用系统提供的方法canvas.drawPath(Path,Paint )将path区域绘制在画布上。

    展开全文
  • leaflet插件实现各种交互效果

    千次阅读 2019-10-12 16:27:19
    然后我们想要实现的各种效果在如下网址 http://develop.smaryun.com:81/API/JS/IGSInterfaceDemoForLeaflet/ 这个网站包含了几乎所有leaflet地图效果 关注微信公众号: 怕夜长梦多 要惊心动魄 求关注 ...

    首当其冲的当然使我们的leaflejs官网文档啦,任何一个插件的使用自然离不开官网文档
    https://leafletjs.com/

    然后我们想要实现的各种效果在如下网址
    http://develop.smaryun.com:81/API/JS/IGSInterfaceDemoForLeaflet/

    这个网站包含了几乎所有leaflet地图效果
    在这里插入图片描述

    展开全文
  • 页面交互效果实现分析

    千次阅读 2017-02-16 11:44:47
    现在前端页面能够实现交互效果越来越酷炫,也越来越复杂。但是这些特效背后的形成机制,却始终简洁优雅。简单说来,一个交互效果实现,是由HTML提供页面骨架,JavaScript负责行为事件,而页面中呈现出的各种各样...

    现在前端页面能够实现的交互效果越来越酷炫,也越来越复杂。但是这些特效背后的形成机制,却始终简洁优雅。

    简单说来,一个交互效果的实现,是由HTML提供页面骨架,JavaScript负责行为事件,而页面中呈现出的各种各样的效果,是由CSS完成的。当然,每一个特效形成的具体原理各有不同,不过也是有规律可寻。

    显示与隐藏

    典型代表: 下拉菜单 提示框

    利用CSS的display属性,在事件发生后实现相应区块内容的显示和隐藏显示和隐藏。 需要注意的是,在具体实现中,最好不要在JS代码直接写style.display,而是通过改变相应内容的className去实现,这样就把JS与CSS很好的进行了分离。这种显示和隐藏,根据不同的情况还存在很多的变体,opactiy(蒙版) 、overflow(图片轮播)。

    数值改变

    典型代表: 顶部广告 图片轮播

    页面中很多元素的CSS属性都是数值型的,结合setInterval() setTimeout()等方法,可以让CSS属性值动态的改变,从而实现一些简单的动画效果。不过对于一些复杂的动画效果,最好是用CSS3去实现,呈现出来会更细腻流畅。

     
    相互关联

    典型代表: 网页定位导航 放大镜

    页面中各元素不是孤立存在的,它们之间也是有许多的联系。,网页定位导航的实现,就是利用了页面内容与导航条间的联系, 放大镜效果,是通过建立鼠标位置的移动与放大展示图片的联系。

    当然这里效果总结只是总体的很小一部分,而且随着CSS3、HTML5等新特性被浏览器的逐渐支持,会有更多新奇好玩的效果出现。等有机会了,再进行总结。

    展开全文
  • 静态网页如何实现动态交互?-JavaScript

    千次阅读 热门讨论 2014-10-30 19:20:23
    静态网页如何实现与用户的静态交互, Javascript的事件处理机制,Javascript在客户机上运行.
  •  JavaScript使网页显示动态效果实现与用户交互功能。    var ss= document.getElementById("con");  ss.style.color="red";  ss.style.backgroundColor="#ccc";  function kk()  {  
  • processing实现动态交互-屁民科普

    万次阅读 多人点赞 2018-11-24 18:43:25
    processing实现动态交互-屁民科普 一开始看了很多的例子,寻找灵感,做了几个小尝试 (因为博主不太会搞动态图,所以这些交互的部分,没有办法看动图233,所以就贴了个图,有点丑陋,想看效果的可以把代码复制...
  • Highcharts AJAX JSON JQuery 实现动态数据交互显示图表
  • jquery实现页面等待时的交互效果

    万次阅读 2015-10-17 17:25:32
    探索这个是因为前端在请求后台有时候需要较长的一段时间,如果不给不用户一些提示性的消息,如正在加载之类的,用户可能会以为页面已死,所以还是得简单的做点交互才行。 思路如下: 在触发请求后台之前便开始等待...
  • 2颗星星+纯CSS实现星星评分交互效果

    千次阅读 2014-11-29 11:59:50
    折腾:2颗星星+纯CSS实现星星评分交互效果 转载自:张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com] 本文地址:http://www.zhangxinxu.com/wordpress/?p=3568 一、星星点灯,照亮我的家门 大家都喜欢...
  • Highcharts AJAX JSON 实现动态数据交互显示 JQuery 图表 柱形图 主要使用的JQuery AJAX JSON SpringMVC 基于之前的2篇框架添加的新功能 这是第一篇实例的步骤与代码。还有整个项目的结构图。 ...
  • 做App原型设计,那么页面切换、进度条、页面滚动、图片轮播,下拉菜单,搜索框这些交互效果必不可少。如何简单快速地实现这些效果呢?以下小编根据经验为大家提供了一些简单的设计方法,以供参考。1.页面跳转作为一...
  • 作者 |黄伟呢来源 | 凹凸数据大家好,我是黄同学交流群预热好久的可视化交互大屏来啦一、项目背景 随着科技的飞速发展,数据呈现爆发式的增长,任何人都摆脱...
  • 卡片式折叠交互效果

    千次阅读 2018-06-01 15:58:23
    你还可以向公众号投稿,将自己总结的技术心得分享给大家....RSS订阅原Android卡片式折叠交互效果2017年08月21日 08:00:05阅读数:145今日科技快讯近日有报道称:在互联网共享单车最早起步的上海,目前有150万辆共享.....
  • 二、效果展示  本次数据分析的特点在于:使用 Tableau 将数据分析的结果做成 可视化交互大屏,效果如下: 三、爬取数据 基于 51job 招聘网站,我们搜索全国对于 “数据” 岗位的需求,大概有 2000 页。...
  • 本套课程主要讲解怎样添加动画效果,课程围绕两个主题,第一我们需要一个什么样的动画效果;...最终我们会通过一个整体的案例,来讲解交互效果实现,让大家掌握这种简单又炫酷的交互方式,为自己的页面增加色彩!
  • 此项目为JQuery,设计有动态生成网页,实现网页的动画效果,超炫,高端大气的网页,提供有源代码。
  • Nginx+PHP 实现动态网站环境

    千次阅读 2018-12-15 17:07:06
    目的:在CentOS7.x系统上安装Nginx和PHP解释器;搭建Nginx+PHP环境,实现一个基本的动态网站运行环境。
  • 有翻阅了一些国外文章,说的也不是很详细,于是花费时间鼓捣了一下,最终实现了TextView图文混排,加点击交互效果,在这里给大家分享下以免后来者在此处浪费过多时间。 主要用到的有Spanned Click
  • web实现全景图的交互展示

    千次阅读 2020-08-21 03:40:00
    Web实现全景图的交互展示不需要学习其他知识,小白也能实现全景图AR展示一、webVR全景图多种方案实现(aframe,Krpano,three,jquery-vrview等等)二、用krpano之前的一些知识准备三、krpano的购买、下载、注册四、...
  • 2 实现思路2.1 服务架构2.2 传输流程3 实现效果3.1 视频展示4 代码实现4.1 项目结构4.2 Java服务端4.2.1 先做一个netty nio的服务端:4.2.2 服务端的具体处理逻辑4.3 网页客户端实现5 小结 基于websocket协议与netty...
  •  WebViewJavascriptBridge是移动UIView和Html交互通信的桥梁,用作者的话来说就是实现java(ios为oc)和js的互相调用的桥梁。替代了WebView的自带的JavascriptInterface的接口,使得我们的开发更加灵活和安全。 ...
  • 使用JavaScript增强交互效果-当当网-完整的项目案例 北大青鸟课件的一部分,比较完整的项目案例,经实际测试,tab切换时有点小bug
  • 最先利用红外线感应器对人体的身体动作进行捕捉拍照,再利用应用服务器完成系统分析,进而在全息投影画面上形成适当的动作反馈,产生严密细致的交互效果。 互动全息投影构建交互的方法具体有三种: 第一种:运用...
  • 最近要实现图文混排的需求,webview过大,所以想到了用SpannableStringBuilder来实现。...有翻阅了一些国外文章,说的也不是很详细,于是花费时间鼓捣了一下,最终实现了TextView图文混排,加点击交互效果,在
  • 选择网页桌面 他设置桌面的页面是这样的,最上面是壁纸商店和你下载的壁纸两个面板项,在壁纸商店里面选择网页类型,点开一个预览效果觉得可以就下载下来,然后点开上面的本地壁纸。 双击你下载的壁纸就可以将他...
  • Ajax+Servlet实现简单前后端数据交互

    千次阅读 2018-10-11 20:31:39
    新建一个jave ee网站项目。给项目起好名字一直next最后选中web-xml选项,配置xml文件。如图 然后在你的新建项目下的java resource下的src新建servlet文件。 在webcontent下新建html文件,建议给html新建一个...
  • JavaScript(简称”JS”)是一种具有函数优先的轻量级,解释型或即时编译型的动态脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。通常JavaScript脚本是通过...
  • java web——servlet+jsp实现前后台交互

    万次阅读 2017-09-06 17:24:08
    大学生涯终于结束,在公司学习了一段时间的java web方面的知识,结合自己之前的一些理解,想通过几篇文章来对我所接触到的java技术进行梳理与总结,也希望给大家一些参考,由于作者水平有限,难免存在一些不足之处...
  • 文章目录一、实现基于mybatis实现CRUD功能二、验证码与前端的基础实现三、前后端的交互1、前后交互之创建账号2、前后交互之数据库数据传入前端显示3、前后交互之修改密码4、前后交互之删除5、前后交互之权限区别登录...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 104,211
精华内容 41,684
关键字:

网站能实现动态交互效果