轮播视图 ViewFlipper 是 Android 从第一个版本就开始提供的 UI 控件,它能够承载多个 View,但一个时机只会有一个 View 展示在屏幕上。通过 ViewFlipper 我们可以实现很多常见的带有展示类型的功能,类似 Gallery、轮播图、导航栏、广告banner等功能,我们可以通过左右滑动、也可以设置定时自动滚动来切换 View。
移动端产品的图片查看几乎都是全屏预览,可以作用滑动切换图,支持缩放手势等,swiper 天然支持这些功能,同时又可以深度定制,适合制作业务组建嵌入项目。分析一下需求:点击图片查看大图,图片可以手势缩放,同时支持左右切换。其实这就是一个不会自动切换的轮播,通过 swiper 就能实现。可以设计一个方法,方法接收 当前图片和所有图片列表,然后每个图片为一页,生成一个轮播,显示在页面的最上层。1246源码没有跳着走的逻辑,都加上了注释,相对好理解。这个图片查看方法利用了 swiper 提供的滚动、手势缩放、手势拖动、分页的能力,实现相对简单,如果需要自己去实现相应功能,就需要花费大量的经历。
第 2 小节介绍了一个API:setAutoStart(),它是用来实现自动播放的,所以我们可以给 ViewFlipper 加上自动轮播的功能。为了控制自动播放和停止,在布局代码中我们加入两个 Button,样式可以直接借用系统播放器的两个资源文件:@android:drawable/ic_media_play和@android:drawable/ic_media_pause,从名字可以看出这是“播放”和“停止”两个按钮,直接在activity_main.xml中根布局<RelativeLayout/>标签的最后加入以下布局代码: <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentTop="true" android:gravity="center" android:orientation="horizontal"> <Button android:id="@+id/play" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginRight="10dp" android:background="@android:drawable/ic_media_play" /> <Button android:id="@+id/stop" android:layout_width="50dp" android:layout_height="50dp" android:background="@android:drawable/ic_media_pause" /> </LinearLayout>在 Java 代码中监听这两个 Button 的点击事件,在点击播放的时候自动翻下一页,对应的动画就是右边进入和左边退出,即in_from_right和out_from_left。我们可以在布局文件中的<ViewFlipper/>标签中加入android:inAnimation="@anim/in_from_right"android:outAnimation="@anim/out_from_left"或者在 Java 代码中通过mViewFlipper.setInAnimation();mViewFlipper.setOutAnimation();设置入场和出场动画,最终在 MainActivity 的 onCreate()函数的末尾添加如下 Java 代码:findViewById(R.id.play).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mViewFlipper.setAutoStart(true); mViewFlipper.setInAnimation(mContext, R.anim.in_from_right); mViewFlipper.setOutAnimation(mContext, R.anim.out_from_left); mViewFlipper.setFlipInterval(2000); mViewFlipper.startFlipping(); Toast.makeText(MainActivity.this, "启动自动播放", Toast.LENGTH_SHORT).show(); } }); findViewById(R.id.stop).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mViewFlipper.stopFlipping(); Toast.makeText(MainActivity.this, "停止自动播放", Toast.LENGTH_SHORT).show(); } });运行之后点击播放即可实现自动翻页,效果如下:
jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript.(jQuery 官方介绍)
我们如果是编写新闻类网站或者电商类网站,有一个需求是点击图片也可以跳转到对应的详情页面,这个时候就需要用到图片链接了。其实图片链接非常简单,我们只需要在 a 标签中嵌套一个 img 标签即可,这样就可以实现点击图片跳转网页了。
jQuery 可以直接从官网下载,也可以用 npm 安装,也可以使用 bower 等这些包管理工具,本篇幅采用 CDN 的形式引入,本身 jQuery 就是一个 .js 文件,只需引入就能使用。<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>引入之后就可以在全局下通过 jQuery 或者 $ 调用 jQuery 了。<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script><script> console.log($); console.log(jQuery); console.log($ === jQuery); // 输出:true</script>
写入图片方法,见下表。方法描述add_picture(image_path_or_stream,width = None,height = None )插入指定图片对应代码中访问,如下所示:from docx import Documentfrom docx.shared import Ptdocument.add_heading('慕课网简介', level=1)...省略部分代码document.add_picture('logo.jpg')document.add_picture('logo.jpg', Pt(20), Pt(30))document.save('info.docx')代码解释:add_picture() 方法为插入指定图片,并根据宽度和高度缩放。如果未指定宽度或高度,则图片以其原始尺寸显示。代码中共插入了 2 张 logo 图片,第一张没有设置宽度和高度即按原始尺寸插入,第二张根据指定的宽度和高度按比例缩放,参数 Pt 为 points 磅,与字号对应可以参考下图。执行完成后,info.docx 文档效果如下图所示。
from dingtalkchatbot.chatbot import DingtalkChatbotwebhook = "https://oapi.dingtalk.com/robot/send?access_token=c01697dd3c97efecd727491693a2ead2d668e8c5dabeb0c3604f545821fc72b7"xiaoq = DingtalkChatbot(webhook)xiaoq.send_image(pic_url='https://www.imooc.com/static/img/column/icon.png')代码解释:通过 send_image () 方法发送图片,pic_url 为指定的图片地址,执行完成后,效果如下图所示。
工具栏组件的“图片导出”按钮可将图表导出为静态图片,支持 jpeg、png、svg 三种格式,可通过 toolbox.feature.saveAsImage 项进行配置,其中比较重要的配置项有:type:用于设定导出图片的格式,当 renderer = canvas 时,支持 jpeg、png,默认为 png;当 renderer = svg 时仅支持 svg 格式;name:导出的文件名,默认为配置项中的 title.text 值;excludeComponents:导出时需要忽略的组件列表,默认值为 [‘toolbox’];pixelRatio:导出图片的分辨率。例如对于下述配置:1332导出效果:Tips:pixelRatio 定义导出图片的缩放比例,例如上例中图表容器的宽高为 style="width: 600px; height: 400px;",若 pixelRatio = 1 则导出图片分辨率为 600x400;若pixelRatio = 2 则为 1200x800;若 pixelRatio = 0.5 则为 300x200。下限为 0,当数值超过 35 时,导出图片可能为空。除工具栏按钮外,开发者还可以通过 echartsInstance.getDataURL 接口将图表内容导出为 base64 串,该接口接受如下参数:(opts: { // 导出的格式,可选 png, jpeg, svg type?: string, // 导出的图片分辨率比例,默认为 1。 pixelRatio?: number, // 导出的图片背景色,默认使用 option 里的 backgroundColor backgroundColor?: string, // 忽略组件的列表 excludeComponents?: Array<string>,}) => string;结合 getDataURL 接口,下述代码片段同样可实现导出为本地图片文件功能:function saveAsImg(chart) { const img = chart.getDataURL({ backgroundColor: '#fff', excludeComponents: ['legend'], pixelRatio: 1, }); const anchor = document.createElement('a'); anchor.href = img; anchor.setAttribute('download', 'test.jpeg'); anchor.click();}导出效果:导出功能对 bmap 插件失效,无法导出百度地图层。
ImageView 和 TextView 一样是直接继承自 View 的基础控件,顾名思义,TextView 用来展示文本,那 ImageView 就是用来展示图片的了。因为 Android 碎片化严重,在 Android 中图片很容易使用但是却很难控制。不同的机型有不同的屏幕尺寸,导致对图片的适配要求很高。但是 Android 系统为我们提供了强大的图片控件,学好 ImageView 是做好 Android UI 适配的第一步。
PNG 图片属于无损压缩格式,也就是说它会比 JPG 图片更大,而且相比于 JPG,它最大的优势在于可以保存图像的透明通道。换句话说就是图片可以拥有透明、半透明背景。这就极大的方便了广大开发者,我们把同样一张图用分别用 JPG 和 PNG 两种格式放在桌面上给大家展示一下两者间的区别:左边是桌面图标,可以看到图标是透明的。而 PNG 虽然也透明,但是却能看出来有个方形的边框,这个是系统为我们自动添加的,目的是为了便于区分是图标还是图片,实际上这个图片是没有边框阴影的。而最右边的 JPG 就很一目了然了,它将所有原本透明的地方全部填上了白色。
写入图片常用方法,见下表。方法参数描述 insert_bitmap(filename, row, col, x = 0, y = 0, scale_x = 1, scale_y = 1) 其中 filename 为文件名,row 为行索引,col 为列索引,x 为水平方向偏移位置,y 为垂直方向偏移位置,scale_x 与 scale_y 为缩放比例,默认 1,即按 1:1 行展示在指定位置插入图片对应代码中访问,如下所示:ws = wb.add_sheet("sheet1")ws.insert_bitmap("user1.bmp", 0, 0)通过上述代码,可以得知在创建的 sheet1 下,第 1 行第 1 列的位置插入了 user1.bmp 图片。
前面我们学习了如何查看单张图片,那么如果我们想要查看很多张图片要如何进行呢?其实与单张图片的查看几乎完全一样,唯一不同的是,我们想要留意图片的数量以及 Batch 的大小:with file_writer.as_default(): images = np.reshape(x_train[:16], (-1, 28, 28, 1)) tf.summary.image("First 16 train images", images, max_outputs=16, step=0)在这里,我们选择查看训练集的前 16 张图片,因此,我们要将其重新 Reshape 为如下的形状:(图片数量, 图片长, 图片宽, 通道数量)因此这里便是:(16, 28, 28, 1)如果不想计算 Batch 数量,可以直接使用 -1 代替:(-1, 28, 28, 1)于是,在 TensorBoard 之中,我们便可以在 “First 16 train images” 选项卡下面查看到我们的 16 张图片了:
Markdown 本身没有为图片增加特殊的样式,如果我们需要特殊定义,可以通过 手动修改全局样式 <style> 实现。实例 3:圆形图片。#### 使图片圆角<style> img { border-radius: 50% !important; border: 30px solid #eee; }</style>其渲染结果如下:图片来源于网络,版权归原作者所有
ViewFlipper 是 FrameLayout 的子类,我们可以向 ViewFlipper 中插入一个或多个 View,而由于它是直接继承自 ViewAnimator,从名字上我们可以猜到,它可以对我们插入的多个 View 做各种动画效果,最常见的效果就是对图片做定时轮播。
jQuery 使用 $ 或者 jQuery 来生成一个 jQuery 对象,这里统一使用 $。1167$ 可以接受一个 CSS 规范的选择器,用来选择元素,html 方法相当于设置 DOM 节点的 innerHTML 属性。在 DOM 相关章节有提到,如果使用 querySelector 来选择节点,碰到节点不存在的情况下,会返回 null,这样就需要一层判断, jQuery 已经处理好了这些情况。<div>DOM节点</div><div class="element"></div><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script><script> $('.ele').html('<p>这里是用 jQuery 插入的 HTML</p>'); console.log('不会影响正常程序执行');</script>其可以接受的参数不仅仅是 CSS 选择器,也可以是一个原生 DOM 节点,一段 HTML 字符串等。jQuery 选择 $ 作为作为入口名称,一部分是因为简单,原生 DOM 提供的选择 DOM 节点的方法都是一长串,另一个原因是 $ 本身的发音 dollar 和 DOM 的发音接近。
在学习 View 的时候,我们学习过 ImageView。它除了在 xml 的 src 属性中设置图片之外,还可以通过setImageDrawable( )和setBackgroundDrawable( )两个 API 设置图片资源。这两个 API 都包含一个关键词——Drawable,那么我们这一节就来看看,Drawable 到底是个什么东西。
但是它也有一个比较致命的缺点:那就是这个图片永远都是有颜色的,换句话说就是不支持透明背景。在 PS 中,上图就是一张 JPG 图片,因为白色也是颜色。而下图这样才代表没有颜色,代表透明:
在 Markdown 文件中,使用 ") 的形式定义图片实例 1:#### 插入一张图片图片前的文字。图片后的文字渲染结果如下:图片来源于网络,版权归原作者所有该源码渲染输出 html 的内容如下:<h4>插入一张图片</h4><p>图片前的文字。</p><p><img src="https://c-ssl.duitang.com/uploads/item/201905/03/20190503105835_VfkU3.thumb.1000_0.png" referrerpolicy="no-referrer"></p><p>图片后的文字。</p>
在我们的网页当中,图片肯定是必不可少的元素,有了图片之后,我们的网页网站就会变得更加的丰富起来。那么我们要在 HTML 当中插入图片的话,就会用到我们的 img 图片标签了。例如:图文并茂的网站。
在前面的学习之中,我们能输入的图片都是内置的图片或者数据集的图片。那么我们在这一小节便来学习一下如何将自己绘制的图片输入到 TensorBoard 之中。这里涉及到一定的绘图知识,因此我们不会绘制过于复杂的图片,我们会绘制一张简单的图片,然后将其输出到 TensorBoard 之中。首先我们要绘制出一张我们自定义的图片:import matplotlib.pyplot as pltimport iofigure = plt.figure()# 绘图x = [1, 2, 3, 4]y = [1.2, 2.5, 4.5, 7.5]plt.plot(x, y)在这张图片之中,我们简单地绘制了一条线段。然后我们便可以将其保存为 PNG 格式:# 定义缓存区buf = io.BytesIO()# 保存为png图片plt.savefig(buf, format='png')# 关闭画布plt.close(figure)buf.seek(0)然后我们将保存好的png图片转化为TensorFlow的图片格式:# 转化为TensorFlow的图片格式image = tf.image.decode_png(buf.getvalue(), channels=4)# 增添一维数据,表示Batchimage = tf.expand_dims(image, 0)最后我们便可以将图片输出到 TensorBoard 日志:with file_writer.as_default(): tf.summary.image("Own Image", image, step=0)然后我们便可以看到我们的图片的形式:
因为我们使用的 Ajax 方法是 jQuery 提供的,因此我们需要在页面中引入 jQuery 脚本。<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>Tips: 注意 jQuery 脚本要放在使用到 jQuery 的脚本之前,这样才可以在我们的页面中愉快的玩耍~
既然 tf.keras 是我们在实际工作中使用最多的工具,那么这节课我们首先来学习如何使用 tf.keras 进行图片的分类。这节课会介绍图像分类网络的常用的网络层、如何处理图片数据以及整体程序的结构。在这里我们采用的是 Kaggle 上的猫狗分类数据集,该数据集合的数据的标签分为猫和狗两个类别,他们的数量分别为:训练集合 2000 张图片,包括 1000 张狗图片和 1000 张猫图片;验证集合 1000 张图片,包括 500 张狗图片和 500 张猫图片。我们会按照获取数据、准备数据、训练数据、数据可视化的顺序帮助大家理解图片分类的过程。通过学习该节课程,我们会得到一个能够分辨猫图片和狗图片、正确率在 70% 以上的分类模型。
我们在训练的过程之中可能要查看一下数据的基本样式,那么我们便可以使用 TensorBoard 来进行图片的查看工作,这边我们仍然以 Mnist 数据集为例。首先我们需要导入数据:import numpy as npimport tensorflow as tf(x_train, y_train),(x_test, y_test) = tf.keras.datasets.mnist.load_data()比如,我们要查看第一张训练集的图片:file_writer = tf.summary.create_file_writer("logs/images/1")img = np.reshape(x_train[0], (1, 28, 28, 1))with file_writer.as_default(): tf.summary.image("First train data", img, step=0)首先,我们将日志目录定义在了 logs/images/1 文件夹下,然后我们通过以下 API 来实现图片数据的输出:tf.summary.image("First train data", img, step=0)其中第一个参数为名称,也就是图片的标签,第二个参数为图片本身,第三个图片为当前的步数,如果只查看静态图片,那么设置为 step=0 就看足够了。然后我们启动 TensorBoard ,便可以在浏览器的 Image 选项卡之中查看到具体的图片了:通过左边的调节器,我们可以调节明暗度和对比度。
在开发过程中,为了提高开发效率,我们会将代码块和一些功能组件进行封装,便于我们更好的复用。插件的作用和这个差不多,将一个功能单独抽离出来,将配置项等其他部分都配置好,就算是一个插件了。比如我们常见的前端插件有轮播图、弹窗等,我们开发时需要用到轮播图的时候,就不需要去从头开始写轮播图的代码了,直接引用轮播图的插件就可以实现开发需求。大家有没有发现,从项目环境搭建、框架搭建,再到填充代码、打包上线,我们的开发过程很像是在搭建一个房子。插件就可以理解为搭建房子的一块块砖头,别人已经帮我们烧制好了,我们直接垒上去就可以。
swiper 本身的定位并不是轮播,轮播是其应用场景之一,发挥想象,可以用 swiper 做许多事情。
Swiper 常用于移动端网站的内容触摸滑动Swiper 是纯 JavaScript 打造的滑动特效插件,面向手机、平板电脑等移动终端。swiper.js 在国内使用面非常广,可以用于实现轮播、图片预览、可滚动应用等,发挥想象可是实现诸多需求。本篇幅采用 swiper5,所有版本的 api 都很相似,主要区别可以参考官方的提供的说明。
减少网页的 http 请求。 利用雪碧图能够很好地减少网页的 http 请求,从而大大的提高页面的性能,这也是其最大的优点,也是其被广泛传播和应用的主要原因。减少图片的大小。 雪碧图能够减少图片的大小,3 张图片合并成 1 张图片的大小比这 3 张图片加起来的大小还要小。简化图片命名。 解决了在图片命名上的困扰,只需对一张雪碧图命名就可以了,不需要对每一个小元素进行命名,从而减少了掉头发的次数。方便更换主题。 只需要在一张或少张图片上修改图片的颜色或样式,整个网页的风格就可以改变。维护起来更加方便。
本节学习了一个很方便实现幻灯片、轮播图的控件:ViewFlipper,在运营活动、广告 Banner 等场景非常常见,可以通过 xml 静态或者 API 动态设置动画及翻转时间间隔,也可以主动触发上翻和下翻动作。大家可以自己思考一下,如果不用 ViewFlipper,只用前面讲的基础布局如何实现这个效果。
使用切片创建视图修改数组元素会影响到原始数组。arr = np.arange(12)print ("数组arr:", arr)创建的 arr 数组为:数组arr: [ 0 1 2 3 4 5 6 7 8 9 10 11]分别通过切片产生 a 和 b:a=arr[3:]b=arr[3:]print("修改前的切片a:", a)print("修改前的切片b:", b)切片结果 a 和 b 为:修改前的切片a: [ 3 4 5 6 7 8 9 10 11]修改前的切片b: [ 3 4 5 6 7 8 9 10 11]分别改变切片 a 和 b 中的元素:a[1]=123b[2]=234print("修改后的切片a:", a)print("修改后的切片b:", b)修改后的 a 和 b 为:修改后的切片a: [ 3 123 234 6 7 8 9 10 11]修改后的切片b: [ 3 123 234 6 7 8 9 10 11]可以看到,对 a 和 b 所做的修改,都同时出现了。这说明切片直接是互相影响的。print("修改后的原数组arr:", arr)打印结果为:修改后的原数组arr: [ 0 1 2 3 123 234 6 7 8 9 10 11]综合看下来,我们可以发现:变量 a,b 都是 arr 的一部分视图,对视图的修改会直接反映到原数据和相关切片中。