swift视图容器_如何使用IBDesignable在Swift中创建漂亮的,可重复使用的渐变视图...
swift视图容器
by Lee Dowthwaite
通过李道思韦特
如何使用IBDesignable在Swift中创建漂亮的,可重复使用的渐变视图 (How to create a beautiful, reusable gradient view in Swift with IBDesignable)
This tutorial will demonstrate how to create a versatile, @IBDesignable
gradient view class in Swift 4. You can drop the CAGradientView into storyboards and preview at design time. Or add it programmatically. You can set the colors for two gradient stops (start and end) and gradient direction (in degrees). These properties are completely controllable from the IB inspector.
本教程将演示如何在Swift 4中创建通用的@IBDesignable
渐变视图类。您可以将CAGradientView放到情节提要中并在设计时进行预览。 或以编程方式添加它。 您可以设置两个渐变色标(开始和结束)和渐变方向(以度为单位)的颜色。 这些属性完全可以从IB检查器控制。
为什么需要这个 (Why You Need This)
Designers just love gradients. Admittedly, like blurred backgrounds and drop shadows, they go in and out of fashion with the changing wind. They do tend to be more subtle nowadays, so they need a fair amount of fiddling around to get them just right.
设计师只喜欢渐变。 诚然,就像背景模糊和阴影一样,它们随着风的变化而进出时尚。 如今,它们确实确实更加微妙,因此他们需要大量的摆弄才能使它们正确。
Creating a gradient involves a reasonable amount of work. Tweaking it until your designer is happy can be a time-consuming process. This tutorial shows you how to build a gradient view component you can drop into storyboards and preview right from within Interface Builder.
创建渐变涉及大量的工作。 对其进行调整直到设计师满意为止可能是一个耗时的过程。 本教程向您展示如何构建渐变视图组件,您可以将其放到情节提要中并在Interface Builder中直接预览。
Your designers will love you for it, and you’ll save yourself a lot of time.
您的设计师会为此而爱,您会节省很多时间。
你会建立什么 (What You Will Build)
It’s easy to say you’re going to build a gradient view, but what are the exact requirements? Let’s define them:
说要建立一个渐变视图很容易,但是确切的要求是什么? 让我们定义它们:
It must be a
UIView
subclass它必须是
UIView
子类It must be
@IBDesignable
so it can be previewed in Xcode/Interface Builder它必须是
@IBDesignable
以便可以在Xcode / Interface Builder中预览- It must be completely configurable either in code or in Interface Builder必须在代码或Interface Builder中完全可配置
获取示例项目 (Get the Example Project)
To follow through this tutorial properly you’ll need the example project which you can grab from GitHub.
为了正确地完成本教程,您需要一个示例项目,您可以从GitHub获取该项目。
When you load the project into Xcode and open the example ViewController scene in the storyboard, you will be able to select the gradient view and edit it in the Attributes Inspector, as shown in the image below.
当您将项目加载到Xcode中并在情节提要中打开示例ViewController场景时,将能够选择渐变视图并在Attributes Inspector中对其进行编辑,如下图所示。
关于渐变层 (About Gradient Layers)
NOTE: This is not intended to be an introduction to CAGradientLayer
. If you need a more basic introduction, please read my Mastering CAGradientLayer in Swift tutorial which explains all the background you need.
注意:这并不旨在作为CAGradientLayer
的介绍。 如果您需要更基础的介绍,请阅读我的Swift Mastering CAGradientLayer教程,其中介绍了您需要的所有背景。
There are several ways to achieve a gradient effect in iOS but in this tutorial we will be using CAGradientLayer
. This is a subclass of CALayer
, a Core Animation object that is part of the view’s layer hierarchy. In iOS, UIView
s are described as layer-backed views because their appearance is controlled by their layer
property. Every view has a layer, and just like every UIView
can have multiple subviews, every layer can have multiple sublayers.
有几种方法可以在iOS中实现渐变效果,但是在本教程中,我们将使用CAGradientLayer
。 这是CALayer
的子类, CALayer
是核心动画对象,属于视图层层次结构。 在iOS中, UIView
被描述为层支持的视图,因为其外观由其layer
属性控制。 每个视图都有一个层,就像每个UIView
可以有多个子视图一样,每个层也可以有多个子层。
What this means in practical terms is that each view can have an arbitrarily complex tree of layers to add visual complexity to the view. When working heavily with Core Animation, at some point the developer has to draw the distinction between adding complexity at the CALayer
level and simply adding a new UIView
to achieve the same effect. Usually, the delineation between views and layers is quite obvious. Often because some property of a view is required for the functionality of the app (for instance, a UILabel
or UIButton
is required).
实际上,这意味着每个视图都可以具有任意复杂的层树,以增加视图的视觉复杂性。 在与Core Animation进行大量工作时,开发人员有时必须在CALayer
级别增加复杂性和仅添加新UIView
来实现相同效果之间做出区分。 通常,视图和图层之间的轮廓非常明显。 通常是因为视图的某些属性是应用程序功能所必需的(例如,需要UILabel
或UIButton
)。
When we create rich UIs with lots of subtle graphics, it can become all too easy to increase the complexity of the layer hierarchy. In general, you should avoid this because layers can only be managed in code, not in storyboards. The logic for managing the layer hierarchy can become quite unwieldy.
当我们创建带有许多微妙图形的丰富UI时,增加层层次结构的复杂性变得非常容易。 通常,应避免这种情况,因为图层只能在代码中进行管理,而不能在情节提要中进行管理。 管理层层次结构的逻辑可能变得非常笨拙。
For the purposes of this tutorial, you will add a single CAGradientLayer
as a sublayer on the view’s layer
property. This gives a one-to-one mapping between views and layers. It nicely encapsulates each gradient layer inside a UIView so it can be laid out in a storyboard.
就本教程而言,您将在视图的layer
属性上添加一个CAGradientLayer
作为子layer
。 这给出了视图和图层之间的一对一映射。 它很好地将每个渐变层封装在UIView中,因此可以将其放置在情节提要中。
定义视图子类 (Defining the View Subclass)
The core of this tutorial is a gradient view called LDGradientView
. It is a subclass of UIView
and is defined as follows:
本教程的核心是一个名为LDGradientView
的渐变视图。 它是UIView
的子类,定义如下:
@IBDesignable class LDGradientView: UIView { // ... }
The class is marked as @IBDesignable
which means it can be previewed in Interface Builder (Xcode’s storyboard editor).
该类被标记为@IBDesignable
,这意味着可以在Interface Builder(Xcode的故事板编辑器)中对其进行预览。
The gradient itself is defined as a private property of the class:
渐变本身定义为该类的私有属性:
// the gradient layer private var gradient: CAGradientLayer?
This property is created by the function below. It sets the gradient’s frame
property to the view’s bounds, thereby taking up the entire view. This is in keeping with the one-to-one mapping between view and layer.
此属性由下面的函数创建。 它将渐变的frame
属性设置为视图的边界,从而占据整个视图。 这与视图和图层之间的一对一映射保持一致。
// create gradient layer private func createGradient() -> CAGradientLayer { let gradient = CAGradientLayer() gradient.frame = self.bounds return gradient }
Then it is added as a subview of the view’s layer as shown:
然后将其添加为视图图层的子视图,如下所示:
// Create a gradient and install it on the layer private func installGradient() { // if there's already a gradient installed on the layer, remove it if let gradient = self.gradient { gradient.removeFromSuperlayer() } let gradient = createGradient() self.layer.addSublayer(gradient) self.gradient = gradient}
These are both private functions because a view’s layer hierarchy should be its own business.
这两个都是私有功能,因为视图的层层次结构应该是其自己的业务。
If you are installing the gradient view in a complex hierarchy, or any superview that uses constraints, then every time the frame is set the view must update itself. You can do that by adding these methods:
如果要在复杂的层次结构中安装渐变视图,或使用约束的任何超级视图,则每次设置框架时,视图都必须更新。 您可以通过添加以下方法来做到这一点:
override var frame: CGRect { didSet { updateGradient() }}
override func layoutSubviews() { super.layoutSubviews() // this is crucial when constraints are used in superviews updateGradient()}
// Update an existing gradient private func updateGradient() { if let gradient = self.gradient { let startColor = self.startColor ?? UIColor.clear let endColor = self.endColor ?? UIColor.clear gradient.colors = [startColor.cgColor, endColor.cgColor] let (start, end) = gradientPointsForAngle(self.angle) gradient.startPoint = start gradient.endPoint = end gradient.frame = self.bounds } }
Finally, we also need some way of instantiating the view and calling the installGradient
function. We do this from one of two initializers, the first to initialize from Interface Builder, and the second for programmatic instantiation:
最后,我们还需要某种方法来实例化视图并调用installGradient
函数。 我们使用两个初始化程序之一进行此操作,第一个初始化程序通过Interface Builder进行初始化,第二个初始化程序以编程方式进行实例化:
// initializers required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) installGradient() }
override init(frame: CGRect) { super.init(frame: frame) installGradient() }
定义渐变 (Defining a Gradient)
Now you have a UIView
subclass that can install a CAGradientLayer
, but that doesn’t achieve a whole lot. Let’s make the gradient view work for us…
现在,您有了一个UIView
子类,该子类可以安装CAGradientLayer
,但是并不能实现很多功能。 让我们为我们制作渐变视图…
There are two main properties of CAGradientLayer
that your custom view will be manipulating. These are:
自定义视图将操作CAGradientLayer
两个主要属性。 这些是:
- The gradient’s colors渐变的颜色
- The gradient’s direction渐变的方向
定义颜色 (Defining the Colors)
The colors are defined as a property on CAGradientLayer
:
颜色定义为CAGradientLayer
的属性:
// An array of CGColorRef objects defining the color of each gradient stop. Animatable.var colors: [Any]?
关于渐变停止的注释 (A Note on Gradient Stops)
The points at which the color changes in a gradient are called gradient stops. Gradients do support fairly complex behavior and can have unlimited stops. Programming this behavior is straightforward. Creating an @IBInspectable
interface for it, however, is more challenging.
颜色在渐变中发生变化的点称为渐变停止点 。 渐变确实支持相当复杂的行为,并且可以有无限次停止。 对这种行为进行编程很简单。 但是,为其创建@IBInspectable
接口更具挑战性。
It would be relatively trivial to add another gradient stop or two. Solving the general problem of an arbitrary number of stops is more difficult. The solution would likely be less usable than doing the same job directly in code.
添加另一个或两个渐变停止点将是相对琐碎的。 解决任意数量的停止的一般问题更加困难。 与直接在代码中完成相同的工作相比,该解决方案的可用性可能更低。
For that reason, this project deals only with “simple” gradients. Ones that start with a color at one edge of the view and fade to another color at the opposite edge.
因此,该项目仅处理“简单”渐变。 在视图的一个边缘以一种颜色开始,然后在相对的边缘以一种颜色逐渐消失的颜色。
If you need to add another stop, you should be able to modify the code easily enough, but it would make the tutorial overly complicated.
如果您需要添加另一个停靠点,则应该能够轻松地修改代码,但是这会使教程过于复杂。
So our implementation of the color stops is simply:
因此,我们对色标的实现很简单:
// the gradient start colour @IBInspectable var startColor: UIColor?
// the gradient end colour @IBInspectable var endColor: UIColor?
These are surfaced in Interface Builder as nice color controls.
这些在Interface Builder中浮出水面,是不错的颜色控件。
定义方向 (Defining the Direction)
The gradient’s direction is defined by two properties on CAGradientLayer
:
渐变的方向由CAGradientLayer
上的两个属性定义:
// The end point of the gradient when drawn in the layer’s coordinate space. Animatable.var endPoint: CGPoint
// The start point of the gradient when drawn in the layer’s coordinate space. Animatable.var startPoint: CGPoint
A gradient’s start and end points are defined in the unit gradient space, which simply means that whatever the dimensions of a given CAGradientLayer
, in the unit gradient space we consider the top left to be position (0, 0) and the bottom right to be position (1, 1), as illustrated below:
渐变的起点和终点是在单位渐变空间中定义的,这仅意味着无论给定CAGradientLayer
的尺寸CAGradientLayer
,在单位渐变空间中,我们都将左上角视为位置(0,0),将右下角视为位置位置(1,1),如下图所示:
This is the CAGradientLayer
coordinate system.
这是CAGradientLayer
坐标系。
The direction is the most challenging part of making a gradient @IBDesignable
. Because of the need for a start and end point, the fact that @IBInspectable
attributes don’t support the CGPoint
data type, not to mention the complete lack of data validation in the UI, our options are a bit limited.
方向是制作@IBDesignable
渐变中最具挑战性的部分。 由于需要起点和终点, @IBInspectable
属性不支持CGPoint
数据类型,更不用说UI中完全缺乏数据验证这一事实,我们的选择有些局限。
When trying to work out the simplest way to define common gradient directions, a string seemed a potentially useful data type and perhaps compass points, e.g. “N”, “S”, “E”, “W” might be useful. But for intermediate directions should it support “NW”? What about “NNW” or “WNW”? And beyond that? That would immediately get confusing. And this way of thinking was clearly a long way round to realizing that the best way to describe any angle on the compass was using degrees!
当尝试找出定义共同梯度方向的最简单方法时,字符串似乎是潜在有用的数据类型,也许罗盘点(例如“ N”,“ S”,“ E”,“ W”)可能有用。 但是对于中间方向,它应该支持“西北”吗? 那“ NNW”或“ WNW”呢? 除此之外呢? 那将立即变得混乱。 而且,这种思维方式显然对于实现描述罗盘上任意角度的最佳方法是使用度数还有很长的路要走!
The user can forget about unit gradient spaces. All the complexity is reduced to a single property exposed to Interface Builder:
用户可以忘记单位梯度空间。 所有复杂性都降低为Interface Builder公开的单个属性:
// the gradient angle, in degrees anticlockwise from 0 (east/right)@IBInspectable var angle: CGFloat = 270
Its default value (270 degrees) points south simply to match the CAGradientLayer
default direction. For a horizontal gradient, set it to 0 or 180.
其默认值(270度) CAGradientLayer
向南以匹配CAGradientLayer
默认方向。 对于水平渐变,请将其设置为0或180。
将角度转换为渐变空间 (Converting the Angle to Gradient Space)
This is the hardest bit. I’m including the code and a description of how it works. You can skip this if you’re just interested in using the class.
这是最难的一点。 我包括了代码及其工作方式的描述。 如果您只对使用该类感兴趣,可以跳过此步骤。
The top-level function to convert the angle to start and end points gradient space looks like this:
将角度转换为起点和终点梯度空间的顶级函数如下所示:
// create vector pointing in direction of angle private func gradientPointsForAngle(_ angle: CGFloat) -> (CGPoint, CGPoint) { // get vector start and end points let end = pointForAngle(angle) let start = oppositePoint(end) // convert to gradient space let p0 = transformToGradientSpace(start) let p1 = transformToGradientSpace(end) return (p0, p1) }
This takes the angle that the user specified and uses it to create a vector pointing in that direction, as illustrated below. The angle specifies the rotation of the vector from 0 degrees. By convention points east in Core Animation, and increases anti-clockwise (counter-clockwise).
如下图所示,这将采用用户指定的角度并将其用于创建指向该方向的矢量。 角度指定矢量从0度开始的旋转。 按照惯例,在Core Animation中指向东方,并逆时针(逆时针)增加。
The end point is found by calling pointForAngle()
, defined thus:
通过调用pointForAngle()
找到pointForAngle()
,定义如下:
private func pointForAngle(_ angle: CGFloat) -> CGPoint { // convert degrees to radians let radians = angle * .pi / 180.0 var x = cos(radians) var y = sin(radians) // (x,y) is in terms unit circle. Extrapolate to unit square to get full vector length if (fabs(x) > fabs(y)) { // extrapolate x to unit length x = x > 0 ? 1 : -1 y = x * tan(radians) } else { // extrapolate y to unit length y = y > 0 ? 1 : -1 x = y / tan(radians) } return CGPoint(x: x, y: y) }
This function looks more complicated than it is. At its core, it simply takes the sine and cosine of the angle to determine the end point on a unit circle. Because Swift’s trigonometry functions (in common with most other languages) require angles to be specified in radians rather than degrees, we have to do that conversion first. Then the x value is calculated by x = cos(radians)
, and the y value by y = sin(radians)
.
此功能看起来比实际要复杂。 从本质上讲,它仅需使用角度的正弦和余弦来确定单位圆上的终点。 由于Swift的三角函数(与其他大多数语言相同)要求以弧度而非角度来指定角度,因此我们必须首先进行转换。 然后,通过x = cos(radians)
计算x = cos(radians)
值,通过y = sin(radians)
计算y值。
The rest of the function is concerned with the fact that the resulting point is on the unit circle. The points we need, however, are in a unit square. Angles along the compass points (i.e. 0, 90, 180 and 270 degrees) will yield the correct result, at the edge of the square. For intermediate angles, the point will be inset from the edge of the square. The vector must be extrapolated to the edge of the square to give the correct visual appearance. This is illustrated below.
函数的其余部分与结果点在单位圆上有关。 但是,我们需要的点在单位平方中。 沿着罗盘点的角度(即0、90、180和270度)将在正方形的边缘产生正确的结果。 对于中间角度,该点将从正方形的边缘开始插入。 必须将向量外推到正方形的边缘以提供正确的视觉外观。 如下所示。
Now we have the end point in a signed unit square, the start point of the vector is found by the simple function below. Because the point is in a signed unit space, it is trivial to find the start point by simply reversing the sign of the components of the end point.
现在我们有一个签署单位正方形终点 ,向量的起点由下面的简单功能找到。 由于该点位于带符号的单位空间中,因此只需简单地反转终点组成部分的正负号即可轻松找到起点。
private func oppositePoint(_ point: CGPoint) -> CGPoint { return CGPoint(x: -point.x, y: -point.y) }
Note that another way to achieve this would have been to add 180 degrees to the original angle and call pointForAngle()
again. But the sign reversal method is so simple that it is slightly more efficient to do it that way.
请注意,实现此目的的另一种方法是将原始角度增加180度,然后再次调用pointForAngle()
。 但是符号反转方法是如此简单,以至于这样做的效率更高。
Now we have the start and end points in the signed unit space, all that remains is to translate them to the unsigned gradient space. The unit space has a y axis that increases northwards. Whereas in the Core Animation space y increases southwards. So the y component must be flipped as part of this translation. The location (0, 0) in our signed unit space becomes (0.5, 0.5) in the gradient space. The function is very straightforward:
现在我们在有符号单位空间中有起点和终点,剩下的就是将它们转换为无符号渐变空间。 单位空间的y轴向北增加。 而在“核心动画”空间中,y向南增加。 因此,在转换过程中必须翻转y分量。 我们的有符号单位空间中的位置(0,0)在渐变空间中变为(0.5,0.5)。 该函数非常简单:
private func transformToGradientSpace(_ point: CGPoint) -> CGPoint { // input point is in signed unit space: (-1,-1) to (1,1) // convert to gradient space: (0,0) to (1,1), with flipped Y axis return CGPoint(x: (point.x + 1) * 0.5, y: 1.0 - (point.y + 1) * 0.5) }
恭喜你! (Congratulations!)
And that is all the hard work done — phew! Congratulations for getting this far — go get yourself a coffee to celebrate…
这就是所有辛勤的工作-! 恭喜您取得了如此远的成就–快来为自己喝杯咖啡庆祝一下…
界面生成器支持 (Interface Builder Support)
All that remains of the gradient view class is the prepareForInterfaceBuilder()
function. This function is only run from with Interface Builder when it needs to render a view. A properly-designed @IBDesignable
view can actually work quite well without it. There will be times – for instance when adding a new view to a storyboard – when it will not render properly until this function is present. You can force it to run by selecting the view in the storyboard and choosing Editor|Debug Selected Views from the menu.
渐变视图类的所有剩余内容是prepareForInterfaceBuilder()
函数。 仅当需要渲染视图时,才通过Interface Builder运行此功能。 没有正确设计的@IBDesignable
视图实际上可以很好地工作。 有时(例如,向情节提要板添加新视图时),直到出现此功能之前,它无法正确呈现。 您可以通过在情节提要板上选择视图,然后从菜单中选择“ 编辑器|调试选定的视图”来强制其运行。
Our implementation of the function simply makes sure the gradient is installed and updated.
我们对该函数的实现只需确保已安装和更新渐变。
override func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() installGradient() updateGradient() }
谢谢阅读! (Thanks for Reading!)
The code for this project is freely available on GitHub.
该项目的代码可在GitHub上免费获得。
Lee Dowthwaite is a veteran iOS developer who’s developed high profile apps for many top-tier clients since 2010.
Lee Dowthwaite是一位资深的iOS开发人员 ,自2010年以来为许多顶级客户开发了高端应用程序。
Originally published at appcodelabs.com on December 10, 2017.
最初于2017年12月10日发布在appcodelabs.com上。
翻译自: https://www.freecodecamp.org/news/how-to-create-a-beautiful-reusable-gradient-view-in-swift-with-ibdesignable-981aebb43d30/
swift视图容器
相关文章:
android 以不规则图片为边框切割另外图片
转自:http://blog.sina.com.cn/s/blog_474928c90101dkvf.html 最近工作上遇到了一个将一个图片按照相框进行裁剪的问题,花了一个下午研究了下,在此整理一下,以便后用。 (相片) …

L3-010. 是否完全二叉搜索树
L3-010. 是否完全二叉搜索树 时间限制400 ms内存限制65536 kB代码长度限制8000 B判题程序Standard作者陈越将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二…

[微信小程序]计算自己手机到指定位置的距离
微信小程序开发交流qq群 581478349 承接微信小程序开发。扫码加微信。 正文: 目的: 根据目的地的坐标计算自己手机的位置离目的地的距离的 核心思路: 后续操作必须等所有异步请求都返回了才能继续 使用Promise() const qqmap require("../../utils/qqma…

ai css 线条粗细_如何训练AI将您的设计模型转换为HTML和CSS
ai css 线条粗细by Emil Wallner埃米尔沃尔纳(Emil Wallner) 如何训练AI将您的设计模型转换为HTML和CSS (How you can train an AI to convert your design mockups into HTML and CSS) Within three years, deep learning will change front-end development. It will increa…
Android Layer List 使用实现实例
Layer List是Anroid中的一种图形的方式,它是通过叠加若干张图片的方式来形成最终的图片,最终的图片在代码中表现为一个LayerDrawable对象。 效果图:第一张是默认显示,第二张为按改变按钮后的图 下面通过一个实例来说明:…

Promise - js异步控制神器
微信小程序开发交流qq群 581478349 承接微信小程序开发。扫码加微信。 正文: 首先给来一个简单的demo看看Promise是怎么使用的: <!DOCTYPE html> <html><head><meta charset"utf-8"><script type"text/ja…

lab_2 Selenium
1、安装SeleniumIDE插件 添加组件-搜索Selenium IDE 安装后重启浏览器可以看到工具中存在此IDE 2、学会使用SeleniumIDE录制脚本和导出脚本 工具--Selenium IDE,得到界面如图 以百度搜索天津大学为例,如下图 红色的是录制按钮,base url是当前…

android进度指示器_等待的痛苦—浏览进度指示器地狱的7个级别
android进度指示器by Mike Zetlow由Mike Zetlow 等待的痛苦—浏览进度指示器地狱的7个级别 (The Pain of Waiting — Navigating the 7 Levels of Progress Indicator Hell) How much hell are you willing to put your users through?您愿意让用户承受多少痛苦? …

Oracle基础 动态SQL语句
一、静态SQL和动态SQL的概念。 1、静态SQL 静态SQL是我们常用的使用SQL语句的方式,就是编写PL/SQL时,SQL语句已经编写好了。因为静态SQL是在编写程序时就确定了,我们只能使用SQL中的DML和事务控制语句,但是DDL语句,以及…

dataTables常用参数
一、新版本和老版本的区别 新版本的改进:https://datatables.net/new/1.10 新老版本参数变化列表:http://datatables.club/upgrade/1.10-convert.html 老版本参数列表: http://legacy.datatables.net/usage/features http://legacy.datatable…
[微信小程序]获取用户当前的城市
有问题可以扫码加我微信,有偿解决问题。承接小程序开发。 微信小程序开发交流qq群 173683895 、 526474645 ; 正文: // 获取用户当前位置的名称和城市 util.jsfunction location() {// 实例化腾讯位置服务里面微信小程序JS SDK的API核心…

构建一个react项目_您想要了解更多有关React的内容吗? 让我们构建一个游戏,然后玩。...
构建一个react项目by Samer Buna通过Samer Buna 您想要了解更多有关React的内容吗? 让我们构建一个游戏,然后玩。 (Do you want to learn more about React? Let’s build — and then play — a game.) Update: This article is now part of my book …

vijos 1476 旅游规划题解
题目链接:https://vijos.org/p/1476 解:因为这一定是一棵树,所以我们多画几次图,就会发现所有的最长路径中心点都一样,且中心点把这条最长路径分成两段等长的路。 那么做法就很简单啦,先求出图的最长路径长…

JQ实现导航效果(附效果图)
微信小程序开发交流qq群 581478349 承接微信小程序开发。扫码加微信。 正文: 为了不浪费大家时间, 首先来一张效果图看是不是你需要的 下面是完整的代码和详细的注释. 直接copy就可以用了. html <div id"tab" class"tab"><div…

.NET如何从配置文件中获取连接字符串
一.设置配置文件 <configuration><!--在configuration下创建一个connectionStrings--><connectionStrings><!--以类似键值对的形式,设置好名字和连接字符串--><add name"连接名" connectionString"连接字符串"/>…

javascript 代码_如何使您JavaScript代码保持简单并提高其可读性
javascript 代码by Leonardo Lima莱昂纳多利马(Leonardo Lima) 如何使您JavaScript代码保持简单并提高其可读性 (How to keep your JavaScript code simple and increase its readability) After a few years working almost exclusively with Ruby on Rails and some jQuery,…

《转》Python学习(14)-对文件的操作(一)
转自 http://www.cnblogs.com/BeginMan/p/3166644.html 一、文件对象 我理解的文件对象就是一个接口,通过这个接口对文件进行相关操作。 《Python 核心编程》上说的很晦涩,这里没有深刻理解到,希望有人能解释给我听。 >>> f open(d…

[微信小程序]组件化开发,以一个自定义模块框组件当做示例(附完整示例代码和效果图)
微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文: 自定义组件我把它分为简单的三个步骤, 1.创建组件 --- 2.编写组件 --- 3.调用,使用组件. 第一步:创建组件 创建一个modal文件夹,里面包含 josn.wxml.wcss.js 四个文件,然后在jo…

openstack安装在虚拟机上重启之后无法启动问题
http://www.byywee.com/page/M0/S931/931767.html 运行rejoin-stack.sh脚本的核心: exec screen -c $TOP_DIR/stack-screenrc stack-screenrc文件存储启动的信息: 例如trove的启动 screen -t tr-api bash stuff "/usr/local/bin/trove-api --config…

让我们讨论一下变量,以及为什么要在JavaScript中使用它们。
by Zell Liew由Zell Liew 让我们讨论一下变量,以及为什么要在JavaScript中使用它们。 (Let’s talk about variables — and why you should use them in JavaScript.) The main purpose of coding is to solve problems. For example, what happens when you clic…

Services(服务)
开启服务有两种方式: 如果不会可以看老师的百度音乐盒的案例1、start方式:start方式的生命周期:*服务只会被开启一次,直到用户手动停止 服务才会被销毁*开启需要调用startService 会执行onCreate(),onStartCommand() *注&…

[敏捷开发实践](2) 用于开发和维持复杂产品的敏捷开发框架Scrum
[敏捷开发实践](2) 用于开发和维持复杂产品的敏捷开发框架Scrum 1,Scrum概述 上篇中提到敏捷开发有两种主流的方法,一个是XP,另一个是Scrum,本篇简要介绍Scrum方法。Scrum是一套开发和维护复杂产品的框架或…
js 实现多选框(复选框) 和单选框,下拉框功能完整示例代码附效果图
<!DOCTYPE html> <html><head><meta charset"utf-8" /><script src"http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script><title>单选框,复选框,下拉菜单简单示例</title></head…

ruby on rails_我成为了Ruby on Rails和React的贡献者,你也可以
ruby on railsI am really grateful to have contributed to a few open source projects, including two I currently use on a regular basis: Ruby on Rails and React.我非常感谢为一些开源项目做出了贡献,其中包括我目前定期使用的两个项目: Ruby o…

MySQL加密算法
1.不可逆加密: PASSWORD(),ENCRYPT(,),MD5(),SHA5()。 2.可逆的加密算法: ENCODE(,) DECODE(,):加密解密字符串。该函数有两个参数:被加密或解密的字符串和作为加密或解密基础的密…

js回调函数和函数带参数的使用示例
微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 //demo1 <html><head><meta charset"UTF-8"><script src"http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script></head>&…

mvc-3模型和数据(1)
MVC和命名空间 var User function(atts) {this.attribute atts || {}; } //和具体user相关的方法 User.prototype.destroy function() {}; //和具体user不相关的函数和变量 User.fetchRemove function() {}; var user new User({name:jinks}); user.destroy();构建对象关系…

初步了解:使用JavaScript进行表达式(De Do Do Do,De Da Da Da)
by Donavon West由Donavon West 初步了解:使用JavaScript进行表达式(De Do Do Do,De Da Da Da) (A first look: do expressions in JavaScript (De Do Do Do, De Da Da Da)) This article is not about about the The Police’s 1980 hit song from alb…

div 下 的img水平居中
设置text-align:center; 这个div必须要设置宽度; 如:{text-align:center; width:100%;}转载于:https://www.cnblogs.com/zzd0916/p/6626772.html

Understanding SOAP
Understanding SOAP转载于:https://www.cnblogs.com/daishuguang/p/4227983.html