H5页面中使用html5-canvas总结

thbcm阅读(161)

H5页面中使用html5-canvas总结

html5canvas 插件实现的功能是,将dom节点的内容复制到一个动态创建的<canvas>中,而通过 canvas 对象就可以很方便地将画布的内容转成图片。

github直达:html2canvas

使用方式

html2canvas(domNode, options).then(function(canvas){
    var img = document.createElement('img');
    img.src = canvas.toDataURL();
    // 成功将原生domNode转成img
});

在H5页面中使用

<script src="js/html2canvas.min.js"></script>
// var domNode = document.getElementById('xxId');
html2canvas(domNode, {
    width: Math.floor(domNode.clientWidth),
    height: Math.floor(domNode.clientHeight),
    scale: 2
}).then(function(canvas) {
    //console.log(canvas);
    //document.body.appendChild(canvas);
    var img = document.createElement('img');
    img.src = canvas.toDataURL();
    img.setAttribute('id', 'xxxImage');
    // 将img展示到页面上
    // prependChild(img, domNode);
});

参数解释:

  • width:指定动态创建的 canvas 的 style 宽度,建议和 domNode 的实际宽度一致;
  • height: 指定动态创建的 canvas 的 style 高度,建议和 domNode 的实际高度一致;
  • scale: 缩放比,笔者建议设置为2,这样相当于将 canvas 画布的绘图宽度/高度扩大为style宽度/高度的2倍。这样绘制出来的图片比较清晰,避免出现模糊的问题。

注意事项

1、实测IOS上出现调用 html5canvas 无反应,Android 机型正常。

2、domNode 中所有图片使用<img>标签引入,不要用 background-image 方式。否则可能图片不清晰。

3、跨域图片不显示的问题,增加配置参数{ allowTaint: true, useCORS: true }。

4、png 图片透明度丢失的问题,增加配置参数{ backgroundColor: “transparent” }。

5、不要使用<br/>标签进行文字换行,使用<p>或<div>标签改写。

6、生成部分图片的问题,可能是调用 html5canvas 方法的时候,domNode 节点本身还没有渲染完毕(比如 domNode 节点本身正在参与一个 zoom 动效),加个适当的延时即可。

7、生成图片底部有留白的问题,这个是 domNode 中图片底部本身就有留白,设置图片样式 display:block/inline-block 即可。

干货! 一文教会你 scrapy 爬虫框架的基本使用

thbcm阅读(170)

一、scrapy爬虫框架介绍

在编写爬虫的时候,如果我们使用 requests、aiohttp 等库,需要从头至尾把爬虫完整地实现一遍,比如说异常处理、爬取调度等,如果写的多了,的确会比较麻烦。利用现有的爬虫框架,可以提高编写爬虫的效率,而说到 Python 的爬虫框架,Scrapy 当之无愧是最流行最强大的爬虫框架了。

scrapy介绍

Scrapy 是一个基于 Twisted 的异步处理框架,是纯 Python 实现的爬虫框架,其架构清晰,模块之间的耦合程度低,可扩展性极强,可以灵活完成各种需求。我们只需要定制开发几个模块就可以轻松实现一个爬虫。

scrapy爬虫框架的架构如下图所示:

它有如下几个部分:

  • Scrapy Engine(引擎):用来处理整个系统的数据流处理、触发事务,是整个框架的核心。
  • Item(项目):定义了爬取结果的数据结构,爬取的数据会被赋值成该对象。
  • Scheduler(调度器):用来接受引擎发过来的请求并加入队列中,并在引擎再次请求的时候提供给引擎。
  • Item Pipeline(项目管道):负责处理由蜘蛛从网页中抽取的项目,它的主要任务是清洗、验证和存储数据。
  • Downloader(下载器):用于下载网页内容,并将网页内容返回给Spiders。
  • Spiders(蜘蛛):其内定义了爬取的逻辑和网页的解析规则,它主要负责解析响应并生成提取结果和新的请求。
  • Downloader Middlewares(下载器中间件):位于引擎和下载器之间的钩子框架,主要是处理引擎与下载器之间的请求及响应。
  • Spider Middlewares(Spiders中间件):位于引擎和蜘蛛之间的钩子框架,主要工作是处理蜘蛛输入的响应和输出的结果及新的请求。

Scrapy数据流机制

scrapy 中的数据流由引擎控制,其过程如下:

  • Engine 首先打开一个网站,找到处理该网站的 Spider 并向该 Spider 请求第一个要爬取的 URL。
  • Engine 从 Spider 中获取到第一个要爬取的 URL 并通过 Scheduler 以 Request 的形式调度。
  • Engine 向 Scheduler 请求下一个要爬取的 URL。
  • Scheduler 返回下一个要爬取的 URL 给 Engine,Engine 将 URL 通过 Downloader Middlewares 转发给 Downloader 下载。
  • 一旦页面下载完毕, Downloader 生成一个该页面的 Response,并将其通过 Downloader Middlewares 发送给 Engine。
  • Engine 从下载器中接收到 Response 并通过 Spider Middlewares 发送给 Spider 处理。
  • Spider 处理 Response 并返回爬取到的 Item 及新的 Request 给 Engine。
  • Engine 将 Spider 返回的 Item 给 Item Pipeline,将新的 Request 给 Scheduler。
  • 重复第二步到最后一步,直到 Scheduler 中没有更多的 Request,Engine 关闭该网站,爬取结束。

通过多个组件的相互协作、不同组件完成工作的不同、组件很好地支持异步处理,scrapy 最大限度地利用了网络带宽,大大提高了数据爬取和处理的效率。

二、scrapy的安装和创建项目

pip install Scrapy -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

安装方法参考官方文档:https://docs.scrapy.org/en/latest/intro/install.html

安装完成之后,如果可以正常使用 scrapy 命令,那就是安装成功了。

Scrapy是框架,已经帮我们预先配置好了很多可用的组件和编写爬虫时所用的脚手架,也就是预生成一个项目框架,我们可以基于这个框架来快速编写爬虫。

Scrapy框架是通过命令行来创建项目的,创建项目的命令如下:

scrapy startproject practice

命令执行后,在当前运行目录下便会出现一个文件夹,叫作practice,这就是一个Scrapy 项目框架,我们可以基于这个项目框架来编写爬虫。

project/
    __pycache__
     spiders/
         __pycache__
        __init__.py
        spider1.py
        spider2.py
        ...
    __init__.py
    items.py
    middlewares.py
    pipelines.py
    settings.py
scrapy.cfg

各个文件的功能描述如下:

  • scrapy.cfg:它是 Scrapy 项目的配置文件,其内定义了项目的配置文件路径、部署相关信息等内容。
  • items.py:它定义 Item 数据结构,所有的 Item 的定义都可以放这里。
  • pipelines.py:它定义 Item Pipeline 的实现,所有的 Item Pipeline 的实现都可以放这里。
  • settings.py:它定义项目的全局配置。
  • middlewares.py:它定义 Spider Middlewares 和 Downloader Middlewares 的实现。
  • spiders:其内包含一个个 Spider 的实现,每个 Spider 都有一个文件。

三、scrapy的基本使用

实例1:爬取 Quotes

  • 创建一个 Scrapy 项目。
  • 创建一个 Spider 来抓取站点和处理数据。
  • 通过命令行运行,将抓取的内容导出。

目标URL:http://quotes.toscrape.com/

创建项目

创建一个 scrapy 项目,项目文件可以直接用 scrapy 命令生成,命令如下所示:

scrapy startproject practice    

创建Spider

Spider是自己定义的类,scrapy用它从网页里抓取内容,并解析抓取的结果。这个类必须继承 Scrapy 提供的Spider类scrapy.Spider,还要定义Spider的名称和起始请求,以及怎样处理爬取后的结果的方法。

使用命令行创建一个Spider,命令如下:

cd practice
scrapy genspider quotes quotes.toscrape.com

切换路径到刚才创建的practice文件夹,然后执行genspider命令。第一个参数是Spider的名称,第二个参数是网站域名。执行完毕之后,spiders 文件夹中多了一个quotes.py,它就是刚刚创建的Spider,内容如下:

import scrapy


class QuotesSpider(scrapy.Spider):
    name = "quotes"
    allowed_domains = ["quotes.toscrape.com"]
    start_urls = ['http://quotes.toscrape.com/']


    def parse(self, response):
        pass

可以看到quotes.py里有三个属性——name、allowed_domains 和 start_urls,还有一个方法 parse。

  • name:它是每个项目唯一的名字,用来区分不同的 Spider。
  • allowed_domains:它是允许爬取的域名,如果初始或后续的请求链接不是这个域名下的,则请求链接会被过滤掉。
  • start_urls:它包含了 Spider 在启动时爬取的 url 列表,初始请求是由它来定义的。
  • parse:它是 Spider 的一个方法。默认情况下,被调用时 start_urls 里面的链接构成的请求完成下载执行后,返回的响应就会作为唯一的参数传递给这个函数。该方法负责解析返回的响应、提取数据或者进一步生成要处理的请求。

创建 Item

Item 是保存爬取数据的容器,它的使用方法和字典类似。不过,相比字典,Item 多了额外的保护机制,可以避免拼写错误或者定义字段错误。

创建 Item 需要继承 scrapy.Item 类,并且定义类型为 scrapy.Field 的字段。观察目标网站,我们可以获取到的内容有 text、author、tags。

定义Item,此时进入items.py修改如下:

import scrapy


class QuoteItem(scrapy.Item):
    text = scrapy.Field()
    author = scrapy.Field()
    tags = scrapy.Field()

定义了三个字段,并将类的名称修改为QuoteItem,接下来爬取时会使用到这个 Item。

解析 Response

parse 方法的参数 response 是 start_urls 里面的链接爬取后的结果。所以在 parse 方法中,我们可以直接对 response 变量包含的内容进行解析,比如浏览请求结果的网页源代码,或者进一步分析源代码内容,或者找出结果中的链接而得到下一个请求。

可以看到网页中既有想要提取的数据,又有下一页的链接,这两部分内容都可以进行处理。

首先看看网页结构,如图所示。每一页都有多个 class 为 quote 的区块,每个区块内都包含 text、author、tags。那么我们先找出所有的 quote,然后提取每一个 quote 中的内容。

提取数据的方式可以是 CSS 选择器 或 XPath 选择器

使用 Item

上文定义了 Item,接下来就要使用它了。Item 可以理解为一个字典,不过在声明的时候需要实例化。然后依次用刚才解析的结果赋值 Item 的每一个字段,最后将 Item 返回即可。

import scrapy
from practice.items import QuoteItem


class QuotesSpider(scrapy.Spider):
    name = 'quotes'
    allowed_domains = ['quotes.toscrape.com']
    start_urls = ['http://quotes.toscrape.com/']


    def parse(self, response, **kwargs):
        quotes = response.css('.quote')
        for quote in quotes:
            item = QuoteItem()
            item['text'] = quote.css('.text::text').extract_first()
            item['author'] = quote.css('.author::text').extract_first()
            item['tags'] = quote.css('.tags .tag::text').extract()
            yield item

后续 Request

上面的操作实现了从初始页面抓取内容。实现翻页爬取,这就需要从当前页面中找到信息来生成下一个请求,然后在下一个请求的页面里找到信息再构造下一个请求。这样循环往复迭代,从而实现整站的爬取。

查看网页源代码,可以发现下一页的链接是 /page/2/,但实际上全链接为:http://quotes.toscrape.com/page/2/ ,通过这个链接就可以构造下一个请求。

构造请求时需要用到 scrapy.Request。这里我们传递两个参数—— url 和 callback,这两个参数的说明如下:

  • url:它是请求链接
  • callback:它是回调函数。当指定了该回调函数的请求完成之后,获取到响应,引擎会将该响应作为参数传递给这个回调函数。回调函数进行解析或生成下一个请求,回调函数如上文的 parse() 所示。

由于 parse 就是解析 text、author、tags 的方法,而下一页的结构和刚才已经解析的页面结构是一样的,所以我们可以再次使用 parse 方法来做页面解析。

"""
@Author  :叶庭云
@Date    :2020/10/2 11:40
@CSDN    :https://blog.csdn.net/fyfugoyfa
"""
import scrapy
from practice.items import QuoteItem


class QuotesSpider(scrapy.Spider):
    name = 'quotes'
    allowed_domains = ['quotes.toscrape.com']
    start_urls = ['http://quotes.toscrape.com/']


    def parse(self, response, **kwargs):
        quotes = response.css('.quote')
        for quote in quotes:
            item = QuoteItem()
            item['text'] = quote.css('.text::text').extract_first()
            item['author'] = quote.css('.author::text').extract_first()
            item['tags'] = quote.css('.tags .tag::text').extract()
            yield item
        next_page = response.css('.pager .next a::attr("href")').extract_first()
        next_url = response.urljoin(next_page)
        yield scrapy.Request(url=next_url, callback=self.parse)

运行 接下来,进入目录,运行如下命令:

scrapy crawl quotes -o quotes.csv

命令运行后,项目内多了一个 quotes.csv 文件,文件包含了刚才抓取的所有内容。

输出格式还支持很多种,例如 json、xml、pickle、marshal 等,还支持 ftp、s3 等远程输出,另外还可以通过自定义 ItemExporter 来实现其他的输出。

scrapy crawl quotes -o quotes.json
scrapy crawl quotes -o quotes.xml
scrapy crawl quotes -o quotes.pickle
scrapy crawl quotes -o quotes.marshal
scrapy crawl quotes -o ftp://user:pass@ftp.example.com/path/to/quotes.csv

其中,ftp 输出需要正确配置用户名、密码、地址、输出路径,否则会报错。

通过 scrapy 提供的 Feed Exports,我们可以轻松地输出抓取结果到文件,对于一些小型项目来说,这应该足够了。不过如果想要更复杂的输出,如输出到数据库等,可以灵活使用 Item Pileline 来完成。

实例2:爬取图片

目标URL:http://sc.chinaz.com/tupian/dangaotupian.html

创建项目

scrapy startproject get_img
cd get_img
scrapy genspider img_spider sc.chinaz.com

构造请求

img_spider.py 中定义 start_requests() 方法,比如爬取这个网站里的蛋糕图片,爬取页数为 10,生成 10 次请求,如下所示:

    def start_requests(self):
        for i in range(1, 11):
            if i == 1:
                url = 'http://sc.chinaz.com/tupian/dangaotupian.html'
            else:
                url = f'http://sc.chinaz.com/tupian/dangaotupian_{i}.html'
            yield scrapy.Request(url, self.parse)

编写 items.py

import scrapy


class GetImgItem(scrapy.Item):
    img_url = scrapy.Field()
    img_name = scrapy.Field()

编写 img_spider.py Spider 类定义了如何爬取某个(或某些)网站,包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(抓取item)

"""
@Author  :叶庭云
@Date    :2020/10/2 11:40
@CSDN    :https://blog.csdn.net/fyfugoyfa
"""
import scrapy
from get_img.items import GetImgItem


class ImgSpiderSpider(scrapy.Spider):
    name = 'img_spider'


    def start_requests(self):
        for i in range(1, 11):
            if i == 1:
                url = 'http://sc.chinaz.com/tupian/dangaotupian.html'
            else:
                url = f'http://sc.chinaz.com/tupian/dangaotupian_{i}.html'
            yield scrapy.Request(url, self.parse)


    def parse(self, response, **kwargs):
        src_list = response.xpath('//div[@id="container"]/div/div/a/img/@src2').extract()
        alt_list = response.xpath('//div[@id="container"]/div/div/a/img/@alt').extract()
        for alt, src in zip(alt_list, src_list):
            item = GetImgItem()       # 生成item对象
            # 赋值
            item['img_url'] = src
            item['img_name'] = alt
            yield item

编写管道文件 pipelines.py

Scrapy 提供了专门处理下载的 Pipeline,包括文件下载和图片下载。下载文件和图片的原理与抓取页面的原理一样,因此下载过程支持异步和多线程,十分高效。

from scrapy.pipelines.images import ImagesPipeline  # scrapy图片下载器
from scrapy import Request
from scrapy.exceptions import DropItem


class GetImgPipeline(ImagesPipeline):
    # 请求下载图片
    def get_media_requests(self, item, info):
        yield Request(item['img_url'], meta={'name': item['img_name']})


    def item_completed(self, results, item, info):
        # 分析下载结果并剔除下载失败的图片
        image_paths = [x['path'] for ok, x in results if ok]
        if not image_paths:
            raise DropItem("Item contains no images")
        return item


    # 重写file_path方法,将图片以原来的名称和格式进行保存
    def file_path(self, request, response=None, info=None):
        name = request.meta['name']  # 接收上面meta传递过来的图片名称
        file_name = name + '.jpg'       # 添加图片后缀名
        return file_name

在这里实现了 GetImagPipeline,继承 Scrapy 内置的 ImagesPipeline,重写了下面几个方法:

  • get_media_requests()。它的第一个参数 item 是爬取生成的 Item 对象。我们将它的 url 字段取出来,然后直接生成 Request 对象。此 Request 加入调度队列,等待被调度,执行下载。
  • item_completed(),它是当单个 Item 完成下载时的处理方法。因为可能有个别图片未成功下载,所以需要分析下载结果并剔除下载失败的图片。该方法的第一个参数 results 就是该 Item 对应的下载结果,它是一个列表形式,列表每一个元素是一个元组,其中包含了下载成功或失败的信息。这里我们遍历下载结果找出所有成功的下载列表。如果列表为空,那么说明该 Item 对应的图片下载失败了,随即抛出异常DropItem,该 Item 忽略。否则返回该 Item,说明此 Item 有效。
  • file_path(),它的第一个参数 request 就是当前下载对应的 Request 对象。这个方法用来返回保存的文件名,接收上面meta传递过来的图片名称,将图片以原来的名称和定义格式进行保存。

配置文件 settings.py

# setting.py


BOT_NAME = 'get_img'


SPIDER_MODULES = ['get_img.spiders']
NEWSPIDER_MODULE = 'get_img.spiders'


# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'


# Obey robots.txt rules
ROBOTSTXT_OBEY = False


# Configure maximum concurrent requests performed by Scrapy (default: 16)
CONCURRENT_REQUESTS = 32


# Configure a delay for requests for the same website (default: 0)
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
DOWNLOAD_DELAY = 0.25


# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   'get_img.pipelines.GetImgPipeline': 300,
}


IMAGES_STORE = './images'   # 设置保存图片的路径 会自动创建

运行程序:

# 切换路径到img_spider的目录
scrapy crawl img_spider

scrapy框架爬虫一边爬取一边下载,下载速度非常快。

查看本地 images 文件夹,发现图片都已经成功下载,如图所示:

到现在为止我们就大体知道了 Scrapy 的基本架构并实操创建了一个 Scrapy 项目,编写代码进行了实例抓取,熟悉了 scrapy 爬虫框架的基本使用。之后还需要更加详细地了解和学习 scrapy 的用法,感受它的强大。

作者:叶庭云

原文链接:https://yetingyun.blog.csdn.net/article/details/108217479

HTML5开发基本常识

thbcm阅读(168)

1.什么是HTML5开发工程师?

HTML5 开发工程师是协调 HTML5 设计师、后端程序员实现网站页面或程序界面,优化交互体验的一个职位。

2.HTML5开发工程师需要掌握哪些职业技能?

市场非常需要精通 HTML、CSS、JavaScript、JQuery、Ajax 等这些核心技术,具备互联网交互设计能力,熟悉后端服务器运行环境和数据通讯协议,掌握响应式布局框架,Bootstrap、Angular 等框架的 HTML5 开发工程师。

3.HTML5开发工程师未来的就业前景好吗?

随着 HTML5 行业发展,国外 HTML5 开发和后端开发人员比例为 1:1。国内目前依旧在 1:3 以下,HTML5 开发职位目前的人才缺口达到近50万人。

4.HTML5工程师需要学习的内容,主要有哪些?

第一阶段 HTML 页面结构和 CSS3 属性

HTML 语句,HTML 页面结构、css 语法、style 属性、link 和 style 标签、id 属性、等 HTML 语句中的相关属性。浏览器兼容性问题处理:XHTML 与 CSS 校验,XHTML 校验器,CSS 校验器。解决如:Chrome、Safari、firefox、opera 等主流浏览器的兼容问题。学习 CSS3 属性,结合 HTML 制作静态页面效果。

第二阶段 Javascript 特效语句

JavaScript 基础语法、数组 Object、Function、String 和 正则表达式、常用内置对象、JSON、错误处理、面向对象高级编程。JavaScrip 的引入及插入位置、JS 元素的获取及简单的函数引用、JS的页面输出及注释语句、变量及 JS 的数据类型、表单的简单应用及JS的操作符等。

第三阶段 jQuery 与 JavaScript 实战课程案例

Jquery 入门和实战 jQuery 使用户能更方便地处理 HTML documents、events、实现动画效果,并且方便地为网站提供 AJAX 交互。

第四阶段 微信小程序等混合应用开发

包括初识微信公众号,订阅号的基本功能,使用百度 BAE 实现代码的快速上线,使用 Git 完成线上代码部署,公众号开发权限及功能接入,微信 JSSDK 接口 API,微信场景项目开发与接入等等。

CSS的两种盒模型

thbcm阅读(173)

IE的盒模型

问题

 下面的代码可以直接复制出去运行哦

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>css盒模型</title>
</head>
<style type="text/css">
.content {
	width: 300px;
	height: 400px;
	border: 5px solid #242424;
	padding: 20px;
	background-color: #898989;
}
</style>
<body>
	<div class="content" id="zwkkkk1"></div>
</body>
</html>

上面代码的逻辑很简单,就是设一个宽 300px,高 400px 的 div,并设置 5px 的边框和 20px 的 padding。然后我们来看效果:

这里我们会发现明明我们设置了 300*400 长宽比,为什么呈现出来的是一个 350*450 的盒子呢?接着让我们打开调试页面一探究竟。

我们可以找到下面的这张示意图:

在这张图中,我们发现我们设置的300*400出现在了最里面的那个蓝框中,与此同时我们可以发现在这个盒模型中除了我们设置的内容(content),还有margin(外边距)、border(边框)、padding(内边框)

margin(外边距)​ – 清除边框外的区域,外边距是透明的。

border(边框)​ – 围绕在内边距和内容外的边框。

padding(内边距)​ – 清除内容周围的区域,内边距是透明的。

content(内容) ​- 盒子的内容,显示文本和图像。

为了正确设置元素在所有浏览器中的宽度和高度,你需要知道盒模型是如何工作的。

而我们在测试效果图看到的​ 350*450​ 盒子,

350(width) = 300(content) + 20(padding)* 2 + 5(border)* 2

450(height)= 400 (content)+ 20(padding)* 2 + 5(border)* 2

CSS 的两种盒模型

而引起上面效果的原因来自于 css 的两种盒模型的不同,这里我先对两种盒模型做个介绍。

W3C的标准盒模型

 在标准的盒子模型中,width 指 content 部分的宽度

IE的盒模型

 在 IE 盒子模型中,width 表示 content+padding+border 这三个部分的宽度

我们可以看出我们上面的使用的默认正是 W3C 标准盒模型
而这里盒模型的选取更倾向于项目和开发者的习惯,并没有绝对的好坏之分。

box-sizing的使用

如果想要切换盒模型也很简单,这里需要借助 CSS3的box-sizing属性

box-sizing: ​content-box​ 是W3C盒子模型
box-sizing: ​border-box ​是IE盒子模型

box-sizing 的默认属性是 content-box

css选择器都有几种?

thbcm阅读(187)

学习了 css 选择器,在此做一个知识梳理:

一、基本选择器

1、id选择器(优先级最高 0100)

如:#id{…}

2、类选择器(优先级次之 0010)

如:.class{…}

3、标签选择器 (优先级最低 0001,涉及最广)

如: div{…}

二、加强选择器

1、后代选择器(选择器名称之间采用空格隔开)

如:#wrap p{…id为wrap下的所有p标签….}

2、子代选择器(选择器名称之间采用大于号’>’进行连接)

如:#wrap>p{…id为wrap下的子代p标签…..}

结合实际详细讲解一下这个子代选择器:

样式展示:

3、组合选择器(选择器名称之间采用逗号’,’隔开)

如:#wrap , .con p{…id 为 wrap 和类名为 con 下的 p 标签 都采用此选择器….}

组合选择器的意思是:满足选择器规则的多个标签都采用同一种 css 样式

三、其他加强版选择器

1、通配符选择器(极少使用,意义不大)

如:*{…….}

2、毗邻选择器(也叫相邻选择器,使用概率大,使用加号“+”连接两个选择器)

如:.con+p{…类名为 con 的兄弟 p 标签满足此条件,注意是兄弟级标签,子级标签不行…..}

3、伪类选择器

如:.clearfix:after{…..作用于类名为 clearfix 的标签后的子标签……}

4、属性选择器

暂定讲解

5、解释一下 div .wrap 和 div.wrap 的区别。

注意:div .wrap 和 div.wrap 的书写区别在于 div 和 .wrap 之间是否有空格。

(1)有空格的 div .wrap 选择器,就是我们前面介绍的后代选择器,意思是:div 标签下的所有类名为 wrap 的标签符合筛选。

(2)没有空格的 div.wrap 是直接相连的,意思是:标签名为 div 且类名 为wrap 的符合筛选

如:div.con#box{…“类名为 con 且 id为 box”的 div 标签符合筛选….}

CSS:class选择器的使用

thbcm阅读(203)

本文介绍 css 中 class 选择器的基本用法:为同一个类型的标签设置属性。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
 
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="zh-cn" />
 
<title>class选择器的使用</title>
<!--在 CSS 中,类选择器以一个点号显示。一个类可以被使用多次。-->
<!--语法:A.B C,如table.blueStyle td
    blueStyle:class名;
    table:blueStyle只能作为table的属性;
    td:table之下的td标签的内容将应用blueStyle指定的属性-->
<head>
<style type="text/css">
  .redStyle {color: red}
  .greenStyleForSpan span {color: green}
  table.blueStyle td {background-color:#99f}
</style>
 
</head>
 
<body bgcolor="#eee">
  <!--所有拥有redStyle类的html元素都将显示为红色-->
  <h3>(一)redStyle类被定义在所有的html标签之上</h3>
  <p>我不拥有redStyle类</p>
  <p class="redStyle">我是一个p,拥有redStyle类,所以我是红色的</p>
  <h4 class="redStyle">我是一个h4,拥有redStyle类,所以我是红色的</h4>
 
  <hr/>
  <!--和 id 一样,class 也可被用作派生选择器:-->
  <h3>(二)greenStyleForSpan类被定义在所有的html标签之上并且只对下属span有效</h3>
  <div class="greenStyleForSpan">
    <p>我是一个p,我所属的div具有greenStyleForSpan类。</p>
  </div>
  <div class="greenStyleForSpan">
    <span>我是一个span,我所属的div具有greenStyleForSpan类。</p>
  </div>
  <span class="greenStyleForSpan">我是一个span,我自己具有greenStyleForSpan类。</p>
 
  <hr/>
  <h3>(三)blueStyle类被定义为table的属性,并且只有table下属的td将应用这个属性。</h3>
  <h4>(1)blueStyle类被使用在table上级的div中了,因此table之下的td没有应用blueStyle属性</h4>
  <div class="blueStyle">
    <table cellpadding="10px" border="1">
      <tr>
        <th>省份</th>
        <th>面积</th>
      <tr>
      <tr>
        <td>河南省</th>
        <td>16.8</th>
      <tr>
      <tr>
        <td>湖北省</th>
        <td>18.1</th>
      <tr>
    </table>
  <div>
 
  <h4>(2)blueStyle类被使用在table中了,因此table之下的td应用了blueStyle属性,而table之下的p和th则没有应用这个属性。</h4>
  <table class="blueStyle" cellpadding="10px" border="1">
      <p>我是table中的一个p</p>
      <tr>
        <th>省份</th>
        <th>面积</th>
      <tr>
      <tr>
        <td>河南省</th>
        <td>16.8</th>
      <tr>
      <tr>
        <td>湖北省</th>
        <td>18.1</th>
      <tr>
    </table>
 
</body>
 
</html>

效果图:

Bootstrap前端框架的入门使用

thbcm阅读(183)

Bootstrap 简介: Bootstrap 是最受欢迎的 HTML、CSS 和 JS 框架,用于开发响应式布局、移动设备优先的 WEB 项目。 2011年,twitter 的“一小撮”工程师为了提高他们内部的分析和管理能力,用业余时间为他们的产品构建了一套易用、优雅、灵活、可扩展的前端工具集——BootStrap。Bootstrap 由 MARK OTTO 和 Jacob Thornton 所设计和建立,在 github 上开源之后,迅速成为该站上最多人 watch&fork 的项目。大量工程师踊跃为该项目贡献代码,社区惊人地活跃,代码版本进化非常快速,官方文档质量极其高,同时涌现了许多基于 Bootstrap 建设的网站:界面清新、简洁;要素排版利落大方。 

Bootstrap 的特点: 简单灵活可用于架构流行的用户界面和交互接口的 HTML、CSS、JavaScript 工具集。基于 HTML5、CSS3的Bootstrap,具有大量的诱人特性:友好的学习曲线,卓越的兼容性,响应式设计,12列格网,样式向导文档,自定义 JQuery 插件,完整的类库,基于 Less 等。

Bootstrap 的优势:

1.定义了很多的 CSS 样式和 JS 插件,提高开发人员的工作效率。

2.响应式布局,页面可以兼容不同分辨率的设备。

3.丰富的组件,给用户提供更好的视觉体验。

一.Bootstrap快速入门

1.下载【Bootstrap】 2.在项目中引入 Bootstrap。

3.创建HTML页面:

引入Bootstrap必要的资源文件,参考基本模板。注意其中缺少 jquery.js 文件,需自行下载引入到 Bootstrap下的 js 文件夹。
 
基本模板代码如下:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>Bootstrap HelloWorld</title>
​
    <!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
    <script src="js/jquery-3.2.1.min.js"></script>
    <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
    <script src="js/bootstrap.min.js"></script>
</head>
<body>
    <h1>你好,世界!</h1>
</body>
</html>

2.Bootstrap响应式布局【栅格系统】

Bootstrap 提供了一套响应式、移动设备优先的流式栅格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列。它包含了易于使用的预定义类,还有强大的 mixin 用于生成更具语义的布局。 

3.Bootstrap的CSS样式和JS插件

具体使用方法参考教程文档:
https://www.w3cschool.cn/bootstrap/

前端面试题——HTML5和CSS3

thbcm阅读(205)

1. 列举3个HTML5新标签,3个CSS3新特性。

  • HTML5 新标签 header,nav,article,footer,section,aside,audio,video,embed
  • CSS3 新特性 border-radius ,box-shadow,border-image,background-image,transition.

2. HTML5实现本地临时存储和永久存贮、读取、删除一条 key 为c,value 为 tom 的数据。

// 临时存储 
sessionStorage.setItem('c','tom')
// 永久存贮 
localStorage.setItem('c','tom')
// 读取 
localStorage.getItem('c')
// 删除 
localStorage.removeItem("c");//逐条删
localStorage.clear();//删除全部

3.用 js+css3 实现某 DIV 以50px每秒的速度左移 100px

<style>
    .box{
      width: 100px;
      height: 100px;
      background-color:pink;
      position: relative;
      left: 0;
      top: 0;
    }
  </style>
  <body>
  <div class="box"></div>
  <script>
    // 100*20=2000
    // 获取box
    let box= document.querySelector('.box')
    let left = box.style.left
    var leftnum = Number(left.split('px')[0]) //不要单位
    var num = 1
    var animate = setInterval(() => {
      if(num>=100){
        clearInterval(animate)
      }
      leftnum+=1
      box.style.left = leftnum+'px'
      num++
    }, 20);
  </script>
</body>

4.CSS 实现三栏布局(左右固定200px,中间自适应)

双飞翼布局:都左浮动,中间包一个盒子,padding 隔开两侧宽度。左右两侧都有 margin-left.

<style>
    body {
        min-width: 550px;
      }
      .col {
        float: left; 
      }
      #main {
        width: 100%;
        height: 400px;
        background-color: #ccc;
      }
      #main-wrap {
        margin: 0 200px 0 200px;
      }
      #left {
        width: 200px;
        height: 400px;
        margin-left: -100%;
        background-color: red;
      }
      #right {
        width: 200px;
        height: 400px;
        margin-left: -200px;
        background-color: #ff0000;
      }
  </style>
  <body>
  <div id="container">
    <div id="main" class="col">
      <div id="main-wrap"></div>
    </div>
    <div id="left" class="col"></div>
    <div id="right"class="col"></div>
  </div>
</body>

圣杯布局:中间不包盒子但还是有 padding。

<style>
    #container{
      padding: 0 190px 0 190px;
    }
    .col{
      position: relative;
      float: left;
    }
    #main{
      width: 100%;
      height: 400px;
      background-color: #ddd;
    }
    #left{
      width: 190px;
      height: 400px;
      background-color:red;
      /* 离左边距本身的距离 */
      margin-left: -100%;
      /* 然后又自己向左移了本身的宽度*/
      left: -190px;
    }
    #right{
      width: 190px;
      height: 400px;
      background-color: yellow;
      margin-left: -190px;
      right: -190px;
    }
  </style>
  <body>
  <div id="container">
    <div id="main" class="col"></div>
    <div id="left" class="col"></div>
    <div id="right"class="col"></div>
  </div>
  </body>

 拓展 左右布局

<style>
    html,body{
      height: 100%;
    }
    .left{
      width: 256px;
      height: 100%;
      background-color: #ddd;
      float: left;
    }
    .right{
      width: 100%;
      height: 100%;
      margin-left: 256px;
      background-color: rgb(230, 48, 48);
    }
  </style>
  <body>
  <div class="left"></div>
  <div class="right"></div>
  </body>

5.使用 html5 canvas 绘制实心原形。

<style>
    #canvas{
      width: 500px;
      height: 500px;
    }
</style>
<body>
  <canvas id="canvas"></canvas>
</body>
<script>
    var canvas=document.getElementById("canvas");
	var ctx=canvas.getContext("2d");
	//画一个空心圆
	ctx.beginPath();
	// arc()方法是创建弧/曲线(用于创建圆或部分圆)
	// context.arc(x,y,r,sAngle,eAngle,counterclockwise);
	// 起始角为 0
	// 结束角为 2*Math.PI
	ctx.arc(100,75,50,0,2*Math.PI);
	ctx.lineWidth=5;
	ctx.strokeStyle="green";
	// 使用 stroke()或fill()方法在画布上绘制实际的弧
	ctx.stroke();//画空心圆
	ctx.closePath();
	//画一个实心圆
	// ctx.beginPath();
	// ctx.arc(200,100,50,0,360,false);
	// ctx.fillStyle="red";//填充颜色,默认是黑色
	// ctx.fill();//画实心圆
	// ctx.closePath();
	//空心和实心的组合
	// ctx.beginPath();
	// ctx.arc(100,100,50,0,360,false);
	// ctx.fillStyle="red";
	// ctx.fill();
	// ctx.strokeStyle="green";
	// ctx.stroke();
	// ctx.closePath();
</script>

6.如何使用 css3 动画实现盒子 hover 时高度从10到100的动画?

<style>
    #box{
      width: 100px;
      height: 10px;
      background-color: pink;
      transition: all 1s ease;
    }
    #box:hover{
      height: 100px;
    }
</style>
<body>
  <div id="box"></div>
</body>

jquery和javascript的区别

thbcm阅读(173)

jquery 就对 javascript 的一个扩展,封装,就是让 javascript 更好用,更简单。人家怎么说的来着,jquery 就是要用更少的代码,漂亮的完成更多的功能。JavaScript 与 JQuery 常用方法比较

1、加载DOM区别

JavaScript:

window.onload

function first(){

alert(‘first’);

}

function second(){

alert(‘second’);

}

window.onload = first;

window.onload = second;

//只会执行第二个window.onload;不过可以通过以下方法来进行改进:

window.onload = function(){

first();

second();

}

Jquery:

$(document).ready()

$(document).ready(){

function first(){

alert(‘first’);

}

function second(){

alert(‘second’);

}

$(document).ready(function(){

first();

}

$(document).ready(function(){

second();

}

//两条均会执行

}

2、获取ID

JavaScript:

document.getElementById(‘idName’)

JQuery:

$(‘#idName’)

3、获取Class

JavaScript:

JavaScript没有默认的获取class的方法

JQuery:

$(‘.className’)

4、获取TagName

JavaScript:

document.getElementsByTagName(‘tagName’)

JQuery:

$(‘tagName’)

5、创建对象并加入文档中

JavaScript:

var para = document.createElement(‘p’);

//创建一个 p 元素

document.body.appendElement(para);

//将 p 元素追加为 body 的 lastchild 子节点,如果想将新创建的 p 元素插入到已存在的某个元素之前,可以使用 insertBefore() 方法

JQuery:

JQuery提供了4种将新元素插入到已有元素(内部)之前或者之后的方法:append()、appendTo()、prepend()、prependTo()。

格式:$( html );

eg,html代码:

<p>World!</p>

$(‘p’).append(‘<b>Hello!</b>’);

//输出:<p>World!<b>Hello!</b></p>

$(‘<b>Hello!</b>’).appendTo(‘p’); //输出:同上

$(‘p’).prepend(‘<b>Hello!</b>’);

//输出:<p><b>Hello!</b>World! </p>

$(‘<b>Hello!</b>’).prependTo(‘p’);

//输出:同上

6、插入新元素

JavaScript:

insertBefore() 语法格式:

parentElement.insertBefore(newElement,targetElement)

eg, 将一个 img 元素插入一个段落之前。

html代码:

<img src=”image.jpg” id=”imgs” />

<p>这是一段文字</p>

JavaScript代码:

var imgs = document.getElementById(‘imgs’);

var para = document.getElementsByTag(‘p’);

para.parenetNode.insertBefore(imgs,para);

JQuery:

JQuery提供了4种将新元素插入到已有元素(外部)之前或者之后的方法:after()、insertAfter()、before()、insertBefore()。

格式:$( html );

eg,html代码:

<p>World!</p>

JQuery代码

$(‘p’).after(‘<b>Hello!</b>’);

//输出:<p>World! </p><b>Hello!</b>

$(‘<b>Hello!</b>’). insertAfter (‘p’);

//输出:同上

$(‘p’).before(‘<b>Hello!</b>’);

//输出:<b>Hello!</b><p>World! </p>

$(‘<b>Hello!</b>’).insertBefore(‘p’);

//输出:同上

7、复制节点

JavaScript:

reference = node.cloneNode(deep)

这个方法只有一个布尔型的参数,它的可取值只能是 true 或者 false。该参数决定是否把被复制节点的子节点也一同复制到新建节点里去。

JQuery:

clone() //复制节点后,被复制的新元素并不具有任何行为

clone(true) //复制节点内容及其绑定的事件

备注:该方法通常与 appendTo()、prependTo()等方法结合使用。

8、删除节点

JavaScript:

reference = element.removeChild(node)

removeChild() 方法将一个给定元素里删除一个子节点

JQuery:

remove();

remove()方法作用就是从 DOM 中删除所有匹配的元素,remove() 方法还可以与其他的过滤选择器结合使用,非常方便。

eg,将 ul li 下的 title 不是”Hello”的li移除:

$(‘ul li’).remove(li[title!=’Hello’]);

empty();

empty()方法作用是清空节点。

9、包裹节点

JavaScript:
JavaScript暂无

JQuery:

wrap() //将匹配元素用其他元素的结构化标记单独包裹起来

wrapAll() //将所有匹配的元素用一个元素包裹起来

wrapInner() //将匹配元素的子内容用其他结构化的标记包裹起来

10、属性操作:设置属性节点、查找属性节点

JavaScript:

document.getElementsByTagName(‘tagName’)

JQuery:

JQuery中设置和查找属性节点都是:attr() 。


$(‘p’).attr(‘title’); //获取 p 元素的 title 属性;


$(‘p’).attr(‘title’,’My title’); //设置 p 元素的title属性


$(‘p’).attr(‘title’:’My title’,’class’:’myClass’); //当需要添加多个属性时,可以用”名:值”对的形式,中间用逗号隔开。

11、替换节点

JavaScript:

reference = element.replaceChild(newChild,oldChild)

该方法是将一个给定父元素里的一个子节点替换为另外一个节点。

JQuery:

replaceWith()、replaceAll()

eg:

<p>hello</p>

想替换为:

<h2>Hi</h2>

JQuery代码:

$(‘p’) .replaceWith(‘<h2>Hi</h2>’);

或者可以写成:

$(‘<h2>Hi</h2>’).replaceAll(‘p’);

12、CSS-DOM操作

JavaScript:

格式:element.style.property

CSS-DOM 能够读取和设置 style 对象的属性,其不足之处是无法通过它来提取外部 CSS 设置的样式信息,而 JQuery的.css() 方法是可以的。

注意点:CSS 中的如”font-size”这样有”-“的,要使用首字母小写的驼峰式表示,如 fontSize。

JQuery:
格式:$(selector).css()

css() 方法获取元素的样式属性

此外,JQuery 还提供了 height() 和 width() 分别用来获取元素的高度和宽度(均不带单位),而 css(height)、css(width)返回高宽,且带单位。

jQuery是干什么的?

thbcm阅读(178)

主要内容

JQuery 对象

jQuery 是一套兼容多浏览器的 javascript 脚本库. 核心理念是写得更少,做得更多,使用 jQuery 将极大的提高编写 javascript 代码的效率,帮助开发者节省了大量的工作,让写出来的代码更加优雅,更加健壮,”如虎添翼”。同时网络上丰富的 jQuery 插件也让我们的工作变成了”有了 jQuery,一切 so easy。” –因为我们已经站在巨人的肩膀上了。

jQuery 在 2006 年 1 月由美国人 John Resig 在纽约的 barcamp 发布,吸引了来自世界各地的众多 JavaScript 高手加入,由 Dave Methvin 率领团队进行开发。如今,jQuery已经成为最流行的 javascript 框架,在世界前 10000 个访问最多的网站中,有超过 55%在使用 jQuery。

Jquery的下载与安装

下载

从 jquery.com 下载 jQuery 库

版本

jQuery 2.x has the same API as jQuery 1.x, but does not support Internet Explorer 6, 7,or 8. (不支持 ie6 7 8,如果需要下载 1.X)

(1)完整版 : jquery-2.1.4.js –>学习版本(学习源码 想高手学习是最好学习方法)

(2)压缩版 : jquery-2.1.4.min.js –>开发版本(压缩版,减少传输)

目前使用版本:jquery-3.4.1.js

优点

(1)提供了强大的功能函数

(2)解决浏览器兼容性问题

(3)实现丰富的 UI 和插件

(4)纠正错误的脚本知识

安装

在页面引入即可

<script src="js/jquery-3.4.1.js" type="text/javascript" ></script>

Jquery 核心

 $ 符号在 jQuery 中代表对 jQuery 对象的引用, “jQuery”是核心对象。通过该对象可以获取 jQuery 对象,调用 jQuery 提供的方法等。只有 jQuery 对象才能调用 jQuery 提供的方法。

$ <==> jQuery

Dom对象 与 Jquery 包装集对象

明确 Dom 对象和 jQuery 包装集的概念, 将极大的加快我们的学习速度。原始的 DoM 对象只有 DOM 接口提供的方法和属性,通过js代码获取的对象都是 dom 对象;而通过 jQuery 获取的对象是 jQuery 包装集对象,简称 jQuery对象,只有 jQuery 对象才能使用jQuery 提供的方法。

Dom 对象

javascript 中获取 Dom 对象,Dom 对象只有有限的属性和方法:

var div = document.getElementById("testDiv");
var divs = document.getElementsByTagName("div");

Jquery 包装集对象

可以说是 Dom 对象的扩充.在 jQuery 的世界中将所有的对象, 无论是一个还是一组, 都封装成一个 jQuery 包装集,比如获取包含一个元素的 jQuery 包装集:

var jQueryObject = $("#testDiv");

Dom 对象 转 Jquery对象

Dom 对象转为 jQuery对象,只需要利用$()方法进行包装即可

var domDiv = document.getElementById('mydiv');  // 获取Dom对象
mydiv = $(domDiv);

Jquery 对象 转 Dom 对象

jQuery 对象转 Dom 对象,只需要取数组中的元素即可

// 第一种方式 获取jQuery对象
var jqueryDiv = jQuery('#mydiv');
// 第二种方式 获取jQuery对象
jqueryDiv = $('#mydiv');
var dom = jqueryDiv[0]; // 将以获取的jquery对象转为dom

通过遍历 jQuery 对象数组得到的对象是 Dom 对象,可以通过 $() 转为 jQuery 对象

$('#mydiv').each(function() {//遍历
       var jquery = $(this);    
});

案例:

<div id="mydiv">write less, do more</div>
 
<script type="text/javascript">
    console.log("-------------获取dom对象------------------")
    // dom对象
    var domDiv = document.getElementById("mydiv");
    console.log(domDiv);
 
    console.log("-------------获取jquery对象------------------")
    // 获取jquery对象
    // 第一种方式
    var jqueryDiv = jQuery('#mydiv');
    console.log(jqueryDiv);
    // 第二种方式
    jqueryDiv = $('#mydiv');
    console.log(jqueryDiv);
 
    console.log("-------------dom转jquery------------------")
    // dom转jquery包装集/对象
    var obj = $(domDiv);
    console.log(obj);
 
    console.log("-------------jquery转dom------------------")
    // jquery对象转dom对象
    var dom = $('#mydiv')[0]; // 获取jquery对象转为dom
    // 或
    var dom2 = jqueryDiv[0]; // 将jquery对象转为dom
    console.log(dom);
    console.log(dom2);
 
    /* this代表了dom对象,不是jquery对象 */
    console.log("-------------dom转jquery------------------")
    $('#mydiv').each(function() {
   // 通过id选择器选择了id为mydiv的所有元素然后进行遍历
   // 那么遍历出的每个元素就是id为mydiv的标签元素
   // 而this就代表了当前的这个元素
        var jquery = $(this);   
    });
 
    console.log("-------------jquery转dom------------------")
    $('#mydiv').each(function() {
        var dom3 = this;    
    });
</script>

联系我们