将SVN服务器里面的项目删除
2014-08-04 SVN平常用 svn
插件进行项目开发管理,如果要删除项目,就需要安装TortoiseSVN
.
安装成功后,右键
就可以看到TortoiseSVN
提示要求输入服务器或者项目的地址
需要用户名、密码
右击项目,点击delete
日志里写点啥吧~,点击OK
即可
平常用 svn
插件进行项目开发管理,如果要删除项目,就需要安装TortoiseSVN
.
安装成功后,右键
就可以看到TortoiseSVN
提示要求输入服务器或者项目的地址
需要用户名、密码
右击项目,点击delete
日志里写点啥吧~,点击OK
即可
##介绍 http://hibernate.org/tools/
##版本 http://tools.jboss.org/downloads/overview.html
选择对应的版本
至今(2014-12-14) Eclipse Luna 4.4
的最新版本是 `JBoss Tools 4.2.1.Final
##下载
下载安装方式有如下三种:
###1.从marketplace
http://tools.jboss.org/downloads/jbosstools/luna/4.2.0.Beta3.html#marketplace
###2.URL站点更新
http://tools.jboss.org/downloads/jbosstools/luna/4.2.0.Beta3.html#update_site
###3.插件下载
http://tools.jboss.org/downloads/jbosstools/luna/4.2.0.Beta3.html#zips
##使用
###1. 创建Hibernate Configuration File(cfg.xml)
根据要求填入相关配置,测试下能否连接上数据库就行了
###2. 创建Hibernate Console Configuration
选择项目和数据库连接(连接 emsc 在上一步中已经创建了)
选择方言
###3. 使用 Hibernate Code Generation Configurations 自动生成实体
选择 上一步中创建好的 Console Configuration,填写包名
选择要生成的的文件类型
会有一个 “The serializable class SdUser does not declare a static final serialVersionUID field of type long” 的警告
用 eclipse 自动处理这个警告,生成一个 serial version ID 即可
完成
##错误解决
Problems while reading database schema
org.hibernate.HibernateException: could not instantiate RegionFactory
换个项目没有问题。jar 冲突。换不了jar 就再另外一个项目里面把bean ,xml 给生成完了再把代码移回原项目
##参考
1.将EEMS
库中的Dec_TownInfo
表中的数据 复制到 OEM
库的c_townInfo
中(c_townInfo
表事先存在),先要将表的主键设为自增长类型,且列出列名
SET IDENTITY_INSERT [OEM].[dbo].[c_townInfo] ON
insert into [OEM].[dbo].[c_townInfo] (id,name,city_id,code,logo) select * FROM [EEMS].[dbo].[Dec_TownInfo]
2.将EEMS
库中的Dec_TownInfo
表中的数据 复制到 OEM
库的c_townInfo
中(c_townInfo
表事先不存在)
SELECT * INTO [OEM].[dbo].[c_townInfo] FROM [EEMS].[dbo].[Dec_TownInfo]
#设置环境变量 变量名:CATALINA_HOME 变量值:tomcat 安装的路径,如 “C:\apache-tomcat-8.0.9”
#安装 service服务 :
打开命令行提示符窗口
=> 进入Tomcat安装目录==> 进入bin目录下==>
输入:service.bat install
即可
#在eclipse里面配置tomcat,如下图:
本例运行演示了用 Jersey 构建 RESTful 服务中,如何集成 angular,用MVC分层的方式访问 RESTful 服务。
1.完成项目结构
创建相应的目录结构
angularjs 、bootstrap 的js,css文件放别放入相应的目录,
在js目录下再创建 app.js
、controller.js
在partials目录下再创建 create.html
、 list.html
、 detail.html
完整目录结构如下
list.html
填入如下内容,主要是显示用户列表ng-repeat
为 angularjs 迭代器
``作用是数据绑定:
<div class="pull-right">
<a href="#/create" class="btn btn-default" title="Create"><span class="glyphicon glyphicon-plus"></span></a>
</div>
<div class="page-header">
<h3>Users</h3>
</div>
<hr />
<li ng-repeat="user in users | filter:query | orderBy:orderProp" >
<div class="pull-right">
<a href="#/users/" class="btn btn-xs btn-default" title="edit">
<span class="glyphicon glyphicon-pencil"></span></a>
</div>
<h4>userId: </h4>
<p>userName:<a href="#/users/"></a> Age:</p>
<hr />
</li>
<hr />
create.html
用来添加用户信息,ng-model
是模型
<div class="page-header">
<h3>Create</h3>
</div>
<form role="form" name="userForm">
<div class="row"> </div>
<div class="row" ng-class="{'has-error': userForm.userId.$invalid}">
<div class="col-md-1">
<i ng-show="userForm.url.$error.required"
class="glyphicon glyphicon-pencil"></i>
<label for="urlInput">userId</label>
</div>
<div class="col-md-4">
<input
type="test"
class="form-control" id="urlInput"
name="userId" ng-model="user.userId" required>
</div>
</div>
<div class="row"> </div>
<div class="row" ng-class="{'has-error': userForm.userName.$invalid}">
<div class="col-md-1">
<i ng-show="userForm.userName.$error.required"
class="glyphicon glyphicon-pencil"></i>
<label for="nameInput">userName</label>
</div>
<div class="col-md-4">
<input
type="text"
class="form-control error" id="nameInput"
name="userName"
ng-model="user.userName"
required>
</div>
</div>
<div class="row"> </div>
<div class="row" ng-class="{'has-error': userForm.url.$invalid}">
<div class="col-md-1">
<i ng-show="userForm.url.$error.required"
class="glyphicon glyphicon-pencil"></i>
<label for="urlInput">age</label>
</div>
<div class="col-md-4">
<input
type="text"
class="form-control" id="urlInput"
name="age" ng-model="user.age" required>
</div>
</div>
<div class="row" ng-hide="showConfirm">
<div class="col-md-5">
<a href="#users" class="btn">Cancel</a>
<button
ng-click="add()"
ng-disabled="isClean() || userForm.$invalid"
class="btn btn-primary">Save</button>
</div>
</div>
detail.html
用来显示用户信息并提供修改、删除等功能
<form role="form" name="userForm">
<div class="row"> </div>
<div class="row" ng-class="{'has-error': userForm.userId.$invalid}">
<div class="col-md-1">
<i ng-show="userForm.url.$error.required"
class="glyphicon glyphicon-pencil"></i>
<label for="urlInput">userId</label>
</div>
<div class="col-md-4">
<input
type="test"
class="form-control" id="urlInput"
name="userId" ng-model="user.userId" required>
</div>
</div>
<div class="row"> </div>
<div class="row" ng-class="{'has-error': userForm.userName.$invalid}">
<div class="col-md-1">
<i ng-show="userForm.userName.$error.required"
class="glyphicon glyphicon-pencil"></i>
<label for="nameInput">userName</label>
</div>
<div class="col-md-4">
<input
type="text"
class="form-control error" id="nameInput"
name="userName"
ng-model="user.userName"
fend-focus="focusUserNameeInput"
required>
</div>
</div>
<div class="row"> </div>
<div class="row" ng-class="{'has-error': userForm.url.$invalid}">
<div class="col-md-1">
<i ng-show="userForm.url.$error.required"
class="glyphicon glyphicon-pencil"></i>
<label for="urlInput">age</label>
</div>
<div class="col-md-4">
<input
type="text"
class="form-control" id="urlInput"
name="age" ng-model="user.age" required>
</div>
</div>
<div class="row" ng-hide="showConfirm"> </div>
<div class="row" ng-hide="showConfirm">
<div class="col-md-5">
<a href="#users" class="btn">Cancel</a>
<button
ng-click="save()"
ng-disabled="isClean() || userForm.$invalid"
class="btn btn-primary">Save</button>
<button
ng-click="remove()"
ng-show="user.userId"
class="btn btn-danger">Delete</button>
</div>
</div>
</form>
index.html
作为主页面,嵌入其他子页面,ng-app
声明这个是模块,ng-controller
说明他的控制器叫ListCtrl
,ng-view
用来存放子视图(页面)。
<!doctype html>
<html ng-app="appMain" ng-controller="ListCtrl">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/bootstrap.min.css" type="text/css"/>
</head>
<body >
<!-- navbar -->
<div class="container ng-view"></div>
<!-- footer -->
<div id="footer" class="hidden-xs">
<div class="container">
<p class="text-muted">
Project Example - by <a href="http://www.waylau.com" target="_blank">www.waylau.com</a> |
<a href="https://github.com/waylau" target="_blank">GitHub Project</a>
</p>
</div>
</div>
<script src="js/bootstrap-3.1.1.min.js"></script>
<script src="js/angular-1.2.3.js"></script>
<script src="js/angular-resource-1.2.3.js"></script>
<script src="js/angular-route-1.2.3.js"></script>
<script src="js/angular-cookies-1.2.3.js"></script>
<script src="js/app.js"></script>
<script src="js/controller.js"></script>
</body>
</html>
app.js
,声明模块appMain
,提供路由功能,说明了调转到哪个页面,用哪个控制器
angular.module('appMain', ['ngRoute']).config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/users', {templateUrl: 'partials/list.html', controller: ListCtrl}).
when('/users/:userId', {templateUrl: 'partials/detail.html', controller: DetailCtrl}).
when('/create', {
templateUrl: 'partials/create.html',
controller: CreateController
}).
otherwise({redirectTo: '/users'});
}]);
controller.js
,控制器。主要是对业务逻辑的操作,常见的CURD功能,http访问RESTful接口,并且返回数据
var url = 'http://localhost:8089/RestDemo/rest';
function ListCtrl($scope, $http) {
$http.get( url + '/users' ).success(function(data) {
$scope.users = data;
});
$scope.orderProp = 'age';
}
function DetailCtrl($scope, $routeParams, $http) {
$http.get( url + '/users/'+$routeParams.userId).success(function(data) {
$scope.user = data;
});
$scope.save = function() {
$http.put( url + '/users', $scope.user).
success(function(data, status, headers, config){
$location.path('/');
}).error(function(data, status, headers, config){
alert("error"+status);
}) ;
};
$scope.remove = function(){
$http({
method:'DELETE',
url: url + '/users/'+ $scope.user.userId ,
})
.success(function(data, status, headers, config){
$location.path('/');
}).error(function(data, status, headers, config){
alert("error"+status);
}) ;
};
}
function CreateController($scope, $http) {
$scope.add = function() {
$http.post( url + '/users', $scope.user).
success(function(data, status, headers, config){
$location.path('/');
}).error(function(data, status, headers, config){
alert("error"+status);
}) ;
};
}
1.先运行项目
2.可以进行CURD操作
PS:本案例力求简单把 angularjs 访问 RESTful 服务展示出来,在Chrome,firefox,IE上做过测试。
#一、总体说明
本例运行演示了用 Jersey 构建 RESTful 服务中,如何集成 jQuery,用html作为客户端访问 RESTful 服务。
#二、环境
WebContent
创建js
,css
两个目录,并把jQuery 库 放入js
目录下,并在该目录下创建main,js
空文件WebContent
创建index.html
: <!DOCTYPE HTML>
<html>
<head>
<title>jquery Demo (人员管理系统)</title>
<meta charset="utf-8"/>
<link rel="stylesheet" href="css/styles.css" />
<script src="js/jquery-1.7.1.min.js"></script>
<script src="js/main.js"></script>
</head>
<body>
<div class="header">
<button id="btnClear">Clear</button>
<button id="btnRefreash">Refreash</button>
更多实例访问:<a href="http://www.waylau.com" >www.waylau.com</a>
</div>
<div class="leftArea">
<ul id="userList"></ul>
</div>
<form id="wineForm">
<div class="mainArea">
<label>Id:</label> <input id="userId" name="userId" type="text" required/>
<label>Name:</label> <input type="text" id="userName" name="userName" required>
<label>Age:</label> <input type="text" id="age" name="age" required/>
<button id="btnAdd">Add</button>
<button id="btnSave">Save</button>
<button id="btnDelete">Delete</button>
</div>
</form>
</body>
</html>
main.js
// The root URL for the RESTful services
var rootURL = 'http://localhost:8089/RestDemo/rest/users';
var currentUser;
// Retrieve wine list when application starts
findAll();
// Nothing to delete in initial application state
$('#btnDelete').hide();
$('#btnAdd').click(function() {
addUser();
return false;
});
$('#btnSave').click(function() {
updateUser();
return false;
});
$('#btnClear').click(function() {
newUser();
return false;
});
$('#btnDelete').click(function() {
deleteUser();
return false;
});
$('#userList a').live('click', function() {
findById($(this).data('identity'));
});
$('#btnRefreash').click(function() {
findAll();
return false;
});
function newUser() {
$('#btnDelete').hide();
currentUser = {};
renderDetails(currentUser); // Display empty form
}
function findAll() {
console.log('findAll');
$.ajax({
type: 'GET',
url: rootURL,
dataType: "json", // data type of response
success: renderList
});
}
function findById(id) {
console.log('findById: ' + id);
$.ajax({
type: 'GET',
url: rootURL + '/' + id,
dataType: "json",
success: function(data){
$('#btnDelete').show();
console.log('findById success: ' + data.userName);
currentUser = data;
renderDetails(currentUser);
}
});
}
function addUser() {
console.log('addUser');
$.ajax({
type: 'POST',
contentType: 'application/json',
url: rootURL,
dataType: "json",
data: formToJSON(),
success: function(data, textStatus, jqXHR){
alert('User created successfully');
$('#btnDelete').show();
$('#userId').val(data.userId);
},
error: function(jqXHR, textStatus, errorThrown){
alert('addUser error: ' + textStatus);
}
});
}
function updateUser() {
console.log('updateUser');
$.ajax({
type: 'PUT',
contentType: 'application/json',
url: rootURL,
dataType: "json",
data: formToJSON(),
success: function(data, textStatus, jqXHR){
alert('User updated successfully');
},
error: function(jqXHR, textStatus, errorThrown){
alert('updateUser error: ' + textStatus);
}
});
}
function deleteUser() {
console.log('deleteUser');
$.ajax({
type: 'DELETE',
url: rootURL + '/' + $('#userId').val(),
success: function(data, textStatus, jqXHR){
alert('user deleted successfully');
},
error: function(jqXHR, textStatus, errorThrown){
alert('delete user error');
}
});
}
function renderList(data) {
// JAX-RS serializes an empty list as null, and a 'collection of one' as an object (not an 'array of one')
var list = data == null ? [] : (data instanceof Array ? data : [data]);
$('#userList li').remove();
$.each(list, function(index, data) {
$('#userList').append('<li><a href="#" data-identity="' + data.userId + '">'+data.userName+'</a></li>');
});
}
function renderDetails(data) {
$('#userId').val(data.userId);
$('#userName').val(data.userName);
$('#age').val(data.age);
}
// Helper function to serialize all the form fields into a JSON string
function formToJSON() {
var userId = $('#userId').val();
return JSON.stringify({
"userId": userId == "" ? null : userId,
"userName": $('#userName').val(),
"age": $('#age').val()
});
}
css
目录下创建styles.css
文件 * {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 18px;
}
.header {
padding-top: 5px;
}
.leftArea {
position: absolute;
left: 10px;
top: 70px;
bottom: 20px;
width: 260px;
border:solid 1px #CCCCCC;
overflow-y: scroll;
}
.mainArea {
position: absolute;
top: 70px;
bottom: 20px;
left:300px;
overflow-y: scroll;
width:300px;
}
.rightArea {
position: absolute;
top: 70px;
bottom: 20px;
left:650px;
overflow-y: scroll;
width:270px;
}
ul {
list-style-type: none;
padding-left: 0px;
margin-top: 0px;
}
li a {
text-decoration:none;
display: block;
color: #000000;
border-bottom:solid 1px #CCCCCC;
padding: 8px;
}
li a:hover {
background-color: #4B0A1E;
color: #BA8A92;
}
input, textarea {
border:1px solid #ccc;
min-height:30px;
outline: none;
}
.mainArea input {
margin-bottom:15px;
margin-top:5px;
width:280px;
}
textarea {
margin-bottom:15px;
margin-top:5px;
height: 200px;
width:250px;
}
label {
display:block;
}
button {
padding:6px;
}
#searchKey {
width:160px;
}
#四、运行 1.先运行项目
2.可以进行CURD操作
PS:本案例力求简单把jquery访问 RESTful 服务展示出来,代码只在Chrome上做过测试。
本章源码:https://github.com/waylau/RestDemo/tree/master/jersey-demo8-sqlserver-hibernate-spring3-jquery
1.Spring 4
唯一的外部强制性的依库是 jakarta commons-logging
2.Spring 4
与可选的第三方库一般只支持在2010年底或后来发布的版本:特别是,Hibernate 3.6+
, EhCache 2.1+
, Quartz 1.8+
, Groovy 1.8+
, and Joda-Time 2.0+
。作为另外,Spring 4
要求最近的Hibernate Validator 4.3 +
,并支持Jackson 2.0+
(Jackson 1.8/1.9
只保留对 Spring 3.2
支持;现在是处在废弃的状态)。
3.Spring 4
对低支持到 JDK 6 update 18
,在新项目中,最好用Java 7/8
.
4.Java EE 6/7
现在被认为是Spring 4
的最低标准。建议使用JPA 2
和Servlet 3
规范。为了兼容Google
App Engine
和老旧的应用,它可以部署 Spring4
应用到servlet
2.5
环境。然而,强烈建议用 Servlet 3+
作为测试环境
5.Gradle
作为项目构建工具
参考:spring-framework-reference (v4.0.6Release)
#一、总体说明
本例运行演示了用 Jersey 构建 RESTful 服务中,如何集成 Spring3
#二、环境
#三、配置
1.根目录下下创建 Spring 的配置文件applicationContext.xml
;
配置如下:
<?xml version=”1.0” encoding=”UTF-8”?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
>
<!-- 激活那些已经在g容器里注册过的bean -->
<context:annotation-config></context:annotation-config>
<!-- 在容器中注入bean -->
<bean id="UserServiceImpl" class="com.waylau.rest.service.impl.UserServiceImpl"/>
<bean id="UserDaoImpl" class="com.waylau.rest.dao.impl.UserDaoImpl"/>
</beans>
2.在com.waylau.rest.service
和com.waylau.rest.service.impl
下分别增加 UserService 和 UserServiceImpl。
UserService.java
package com.waylau.rest.service;
import java.util.List;
import com.waylau.rest.bean.User;
/**
* User Service 接口
* @author waylau.com
* 2014-7-25
*/
public interface UserService {
public User getUserById(String id);
public boolean deleteUserById(String id);
public boolean createUser(User user);
public boolean updateUser(User user);
public List<User> getAllUsers();
}
UserServiceImpl.java
package com.waylau.rest.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.waylau.rest.bean.User;
import com.waylau.rest.dao.impl.UserDaoImpl;
import com.waylau.rest.service.UserService;
/**
* User Service 接口实现
* @author waylau.com
* 2014-7-25
*/
public class UserServiceImpl implements UserService {
@Autowired
private UserDaoImpl userDaoImpl;
public UserServiceImpl() {
// TODO Auto-generated constructor stub
}
@Override
public User getUserById(String id) {
return userDaoImpl.getUserById(id);
}
@Override
public boolean deleteUserById(String id) {
return userDaoImpl.deleteUserById(id);
}
@Override
public boolean createUser(User user) {
return userDaoImpl.createUser(user);
}
@Override
public boolean updateUser(User user) {
return userDaoImpl.updateUser(user);
}
@Override
public List<User> getAllUsers() {
return userDaoImpl.getAllUsers();
}
}
3.修改 UserResource.java
package com.waylau.rest.resources;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import org.springframework.beans.factory.annotation.Autowired;
import com.waylau.rest.bean.User;
import com.waylau.rest.service.impl.UserServiceImpl;
/**
* 用户资源
* @author waylau.com
* 2014-7-26
*/
@Path("/users")
public class UserResource {
private static final Logger LOGGER = Logger.getLogger(UserResource.class.getName());
@Autowired
private UserServiceImpl userServiceImpl;
public UserResource() {
LOGGER.fine("UserResource()");
}
/**
* 增加
* @param user
*/
@POST
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public void createUser(User user)
{
userServiceImpl.createUser(user);
}
/**
* 删除
* @param id
*/
@DELETE
@Path("{id}")
public void deleteUser(@PathParam("id")String id){
userServiceImpl.deleteUserById(id);
}
/**
* 修改
* @param user
*/
@PUT
@Consumes(MediaType.APPLICATION_XML)
public void updateUser(User user){
userServiceImpl.updateUser(user);
}
/**
* 根据id查询
* @param id
* @return
*/
@GET
@Path("{id}")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public User getUserById(@PathParam("id") String id){
User u = userServiceImpl.getUserById(id);
return u;
}
/**
* 查询所有
* @return
*/
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public List<User> getAllUsers(){
List<User> users = new ArrayList<User>();
users = userServiceImpl.getAllUsers();
return users;
}
}
4.修改web.xml,插入
<module-name>RestDemo</module-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
#四、运行 1.先运行项目
2.运行UserClient.java测试,控制台输出如下
****增加用户addUser****
****查询所有getAllUsers****
[{"userId":"002","userName":"sdfs","age":"23"},{"userId":"003","userName":"sdfs","age":"23"},{"userId":"004","userName":"sdfs","age":"23"},{"userId":"005","userName":"sdfs","age":"23"},{"userId":"006","userName":"Susan","age":"21"},{"userId":"007","userName":"sdfs","age":"23"},{"userId":"ds","userName":"ds","age":"ds"}]
****修改用户updateUser****
****根据id查询用户****
006Susan33
****查询所有getAllUsers****
[{"userId":"002","userName":"sdfs","age":"23"},{"userId":"003","userName":"sdfs","age":"23"},{"userId":"004","userName":"sdfs","age":"23"},{"userId":"005","userName":"sdfs","age":"23"},{"userId":"006","userName":"Susan","age":"33"},{"userId":"007","userName":"sdfs","age":"23"},{"userId":"ds","userName":"ds","age":"ds"}]
****删除用户****
****查询所有getAllUsers****
[{"userId":"002","userName":"sdfs","age":"23"},{"userId":"003","userName":"sdfs","age":"23"},{"userId":"004","userName":"sdfs","age":"23"},{"userId":"005","userName":"sdfs","age":"23"},{"userId":"007","userName":"sdfs","age":"23"},{"userId":"ds","userName":"ds","age":"ds"}]
本章源码(含jar包):https://github.com/waylau/RestDemo/tree/master/jersey-demo7-sqlserver-hibernate-spring3
#综述 本文演示了用Maven编译Java项目
#需要
#创建项目 本例主要为了展示Maven,所以Java的项目力求简单。
#创建项目结构 选择一个项目目录,在 *nix系统上使用下面语句
mkdir -p src/main/java/hello
window下使用命令
mkdir src\main\java\hello
创建如下结构:
└── src
└── main
└── java
└── hello
在src/main/java/hello
目录下创建Java文件HelloWorld.java
和 Greeter.java
src/main/java/hello/HelloWorld.java
package hello;
public class HelloWorld {
public static void main(String[] args) {
Greeter greeter = new Greeter();
System.out.println(greeter.sayHello());
}
}
src/main/java/hello/Greeter.java
package hello;
public class Greeter {
public String sayHello() {
return "Hello world!";
}
}
现在项目完成,可以用Maven编译了。有关Maven的安装,可以参考Apache Maven 3.1.0 安装、部署、使用
#定义简单的Maven编译
首先,在项目的根目录下创建一个Maven项目定义文件pom.xml
,该文件主要是说明项目的名称、版本和依赖库
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-maven</artifactId>
<packaging>jar</packaging>
<version>0.1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>hello.HelloWorld</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
除了<packaging> 元素可选外,其他的元素是构成pom.xml
文件的最基本的元素了。它包括以下几个项目的配置:
#编译Java代码 运行下面语句编译
mvn compile
编译完成的.class
文件将会出现在target/classes
目录下.如下图
运行项目:
mvn exec:java -Dexec.mainClass="hello.HelloWorld"
输出如下:
如果不想直接运行.class
文件,可以将其打包:
mvn package
打包完成后,会在target
目录下生成一个JAR文件,文件名由<artifactId> 和 <version>组成。比如本例,将会根据pom.xml
生成gs-maven-0.1.0.jar
如果你想安装您的项目的JAR文件到本地Maven仓库,那么你应该调用下面语句:
mvn install
此时,你的项目代码将会经过编译、测试、打包并拷贝到本地依赖库,提供给其他项目引用。
以上例子源码的地址https://github.com/waylau/maven-demo中的demo1
说到项目依赖,下面说下声明依赖
#声明依赖 上面的例子比较简单,没有用到其他库。但是真实的项目可能会引用(依赖)到很多其他库。
下面例子,依赖了Joda Time
的库。
修改src/main/java/hello/HelloWorld.java
package hello;
import org.joda.time.LocalTime;
public class HelloWorld {
public static void main(String[] args) {
LocalTime currentTime = new LocalTime();
System.out.println("The current local time is: " + currentTime);
Greeter greeter = new Greeter();
System.out.println(greeter.sayHello());
}
}
现在运行mvn compile
将会报错,因为没有声明依赖。在 <project> 节点下插入如下:
<dependencies>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
这段内容就声明了项目的依赖。每个依赖节点<dependency>都由三个子节点组成:
在POM 4中,<dependency> 中还引入了<scope> ,它主要管理依赖的部署。目前<scope> 可以使用5个值:
现在你运行mvn compile
或者mvn package
,Maven会自动下载相关依赖。
完整的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-maven</artifactId>
<packaging>jar</packaging>
<version>0.1.0</version>
<!-- tag::joda[] -->
<dependencies>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
<!-- end::joda[] -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>hello.HelloWorld</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
运行项目:
mvn exec:java -Dexec.mainClass="hello.HelloWorld"
输出如下:
以上例子源码的地址https://github.com/waylau/maven-demo中的demo2
参考:http://spring.io/guides/gs/maven/
http://www.vineetmanohar.com/2009/11/3-ways-to-run-java-main-from-maven/
#综述 用maven做项目,最郁闷的莫过于某些依赖库下载不了。被墙了,你懂的。使用maven镜像仓库及其重要,特别是国内的镜像,可以有效缓解被墙疼痛。
#常用的镜像
##国外镜像
ibiblio.org
<mirror>
<id>ibiblio</id>
<mirrorOf>central</mirrorOf>
<name>ibiblio Mirror of http://repo1.maven.org/maven2/</name>
<url>http://mirrors.ibiblio.org/pub/mirrors/maven2/</url>
</mirror>
jboss
<mirror>
<id>jboss-public-repository-group</id>
<mirrorOf>central</mirrorOf>
<name>JBoss Public Repository Group</name>
<url>http://repository.jboss.org/nexus/content/groups/public</url>
</mirror>
repo2
<mirror>
<id>repo2</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://repo2.maven.org/maven2/</url>
</mirror>
uk.maven.org
<mirror>
<id>ui</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://uk.maven.org/maven2/</url>
</mirror>
##国内镜像
aliyun.com
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
oschina.net(目前已经不能访问)
<id>nexus-osc</id>
<mirrorOf>*</mirrorOf>
<name>Nexus osc</name>
<url>http://maven.oschina.net/content/groups/public/</url>
</mirror>
net.cn(目前已经不能访问)
<mirror>
<id>net-cn</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://maven.net.cn/content/groups/public/</url>
</mirror>
#使用镜像
在maven的settings.xml 文件里配置mirrors的子节点,添加如下 mirror
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
下文以oschina.net的镜像为例子.
1.Maven 的安装目录下的 conf 文件下有个settings.xml
文件,编辑该文件
2.在<mirrors>中插入:
<id>nexus-osc</id>
<mirrorOf>*</mirrorOf>
<name>Nexus osc</name>
<url>http://maven.oschina.net/content/groups/public/</url>
</mirror>
3.这里是配置 Maven 的 mirror 地址指向OSChina 的 Maven 镜像地址。 在执行 Maven 命令的时候, Maven 还需要安装一些插件包,这些插件包的下载地址也让其指向 oschina.net 的 Maven 地址。在<profiles>中插入:
<profile>
<id>jdk-1.4</id>
<activation>
<jdk>1.4</jdk>
</activation>
<repositories>
<repository>
<id>nexus</id>
<name>local private nexus</name>
<url>http://maven.oschina.net/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>nexus</id>
<name>local private nexus</name>
<url>http://maven.oschina.net/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
#一、综述 在做流程图软件时,折线必不可少。本文展示的是现有系统的简单折线实现。折线主要分为一折折线、二折折线。下面例子默认起点为“图1”,终点为“图2”,假设pt1,pt2为已知点,pt3,pt4为动态计算点。
#二、一折折线
pt3 = ( pt2.x , pt1.y )
#三、二折折线 ##1.pt1 在pt2的左侧
pt3 = ( pt1.x + ( pt2.x – pt1.x )*0.5 , pt1.y )
pt4 = ( pt1.x + ( pt2.x – pt1.x )*0.5 , pt2.y )
##2.pt1 在pt2的右侧
pt3 = ( pt2.x + ( pt1.x – pt2.x )*0.5 , pt1.y )
pt4 = ( pt2.x + ( pt1.x – pt2.x )*0.5 , pt2.y )
#神马是DNSCrypt? 官方提法“DNSCrypt is a piece of lightweight software that everyone should use to boost online privacy and security. It works by encrypting all DNS traffic between the user and OpenDNS, preventing any spying, spoofing or man-in-the-middle attacks.”
可加密DNS流量,阻止常见的DNS攻击,如重放攻击、观察攻击、时序攻击、中间人攻击和解析伪造攻击,是防止DNS污染的绝佳工具。
#神马是DNS污染? 是指一些刻意制造或无意中制造出来的域名服务器分组,把域名指往不正确的IP地址。擦~不就是被“墙”了吗?
#DNSCrypt搞起来! DNSCrypt官方介绍页面:http://www.opendns.com/about/innovations/dnscrypt/
DNSCrypt最新下载地址:http://shared.opendns.com/dnscrypt/packages/windows-client/DNSCryptWin-v0.0.6.exe
安装运行后,亮绿灯
测试下https://www.flickr.com
测试下https://www.facebook.com/
测试下https://www.youtube.com 网速有点慢,今天的主脚竟然是涛哥和温总
因为宝宝吃奶的时候很容易把空气吃进去,所以在宝宝吃完奶之后要给他们拍背,拍背的目的是给宝宝拍嗝,所以不是按时间来说的,只要宝宝打了嗝就可以不再拍了,当然有些宝宝拍很长时间也不打嗝,这是很正常的,遇到这种情况拍一两分钟那就不需要再拍了。
1.爸爸妈妈一手托住宝宝的头,另一手支撑宝宝的屁股,将宝宝竖着抱起来,调整好位置,让宝宝的脸可以靠在大人肩膀上。手掌略为拱起,呈半圆弧、类汤匙状,用空掌的方式轻拍宝宝背部,从背脊或腰部位置,由下往上拍,利用震动原理,慢慢地将宝宝体内的空气拍出来。
2.让宝宝坐在爸爸或妈妈的大腿上,身体侧面稍微靠着爸爸或妈妈的胸口,妈妈用虎口托住宝宝的下巴,另一只手先在宝宝背部轻柔画几个圆圈后,同样以空掌的方式轻拍宝宝背部。
3.用手指托着宝宝的颚骨,扶BB坐直约90度,将手掌微微并拢,呈空心状,从BB背部由下往上扫,直到BB嗝气。不一定是拍,可以是扫的手法,但要留意不要太用力,用力过大也会造成吐奶。
4.宝宝吃好奶以后,就让她上身直立,抱一会儿。因为宝宝还小,脊椎发育还不完善,所以一定要托好她的后背、脊椎以及头颈。一般来说,这样十几二十分钟后,宝宝也会打嗝;或者妈妈端坐着,一只手托住宝宝的脊椎、头颈,也让她上身呈“坐”的姿势,妈妈的另一只手托住宝宝的下巴,这样宝宝会很快打出嗝来
##其他 多给宝宝做腹部按摩消消滞:如果宝宝打嗝的原因是由于乳食停滞不化造成的,那么在宝宝打嗝时就可以闻到不消化的酸腐异味,多给宝宝做腹部的按摩,让宝宝在你的温柔指尖中调整自己的小肚子,帮助“排气”,食消气顺,则嗝自止。
做好腹部的保暖:新生儿若无其他疾病而突然打嗝,并且嗝声高亢有力且连续,一般是受寒凉所致,寒热之气逆而不顺时也容易诱发打嗝,这时可以给宝宝喝点温白开水,因此,天气寒凉时要注意宝宝腹部的保暖,睡觉时注意将被子或衣服盖在宝宝的胸腹部上,夏天开空调时温度不宜太低,以26~28℃为宜。
止嗝小方法:如果小宝宝打嗝不止,可以用手指轻轻挠下宝宝的脚底板,宝宝会因为突然的刺激而停止了打嗝,或者也可以轻轻挠下宝宝的小嘴巴和小耳朵,这里的神经比较敏感,也可以有效地制止打嗝现象。
原始值: 相当于传值
string
number
boolean
null
undefined
var foo = 1,
bar = foo;
bar = 9;
console.log(foo, bar); // => 1, 9
复杂类型: 相当于传引用
object
array
function
var foo = [1, 2],
bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9
使用字面值创建对象
// bad
var item = new Object();
// good
var item = {};
不要使用保留字 reserved words 作为键
// bad
var superman = {
class: 'superhero',
default: { clark: 'kent' },
private: true
};
// good
var superman = {
klass: 'superhero',
defaults: { clark: 'kent' },
hidden: true
};
使用字面值创建数组
// bad
var items = new Array();
// good
var items = [];
如果你不知道数组的长度,使用push
var someStack = [];
// bad
someStack[someStack.length] = 'abracadabra';
// good
someStack.push('abracadabra');
当你需要拷贝数组时使用slice. jsPerf
var len = items.length,
itemsCopy = [],
i;
// bad
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
itemsCopy = items.slice();
使用slice将类数组的对象转成数组.
function trigger() {
var args = Array.prototype.slice.call(arguments);
...
}
对字符串使用单引号 ''
// bad
var name = "Bob Parr";
// good
var name = 'Bob Parr';
// bad
var fullName = "Bob " + this.lastName;
// good
var fullName = 'Bob ' + this.lastName;
注: 如果过度使用,长字符串连接可能会对性能有影响. jsPerf & Discussion
// bad
var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
// bad
var errorMessage = 'This is a super long error that was thrown because \
of Batman. When you stop to think about how Batman had anything to do \
with this, you would get nowhere \
fast.';
// good
var errorMessage = 'This is a super long error that was thrown because ' +
'of Batman. When you stop to think about how Batman had anything to do ' +
'with this, you would get nowhere fast.';
编程时使用join而不是字符串连接来构建字符串,特别是IE: jsPerf.
var items,
messages,
length,
i;
messages = [{
state: 'success',
message: 'This one worked.'
}, {
state: 'success',
message: 'This one worked as well.'
}, {
state: 'error',
message: 'This one did not work.'
}];
length = messages.length;
// bad
function inbox(messages) {
items = '<ul>';
for (i = 0; i < length; i++) {
items += '<li>' + messages[i].message + '</li>';
}
return items + '</ul>';
}
// good
function inbox(messages) {
items = [];
for (i = 0; i < length; i++) {
items[i] = messages[i].message;
}
return '<ul><li>' + items.join('</li><li>') + '</li></ul>';
}
函数表达式:
// 匿名函数表达式
var anonymous = function() {
return true;
};
// 有名函数表达式
var named = function named() {
return true;
};
// 立即调用函数表达式
(function() {
console.log('Welcome to the Internet. Please follow me.');
})();
注: ECMA-262定义把块
定义为一组语句,函数声明不是一个语句。阅读ECMA-262对这个问题的说明.
// bad
if (currentUser) {
function test() {
console.log('Nope.');
}
}
// good
if (currentUser) {
var test = function test() {
console.log('Yup.');
};
}
绝对不要把参数命名为 arguments
, 这将会逾越函数作用域内传过来的 arguments
对象.
// bad
function nope(name, options, arguments) {
// ...stuff...
}
// good
function yup(name, options, args) {
// ...stuff...
}
一般而言,对象中的属性的值是通过点(.)运算符来取值
var luke = {
jedi: true,
age: 28
};
// bad
var isJedi = luke['jedi'];
// good
var isJedi = luke.jedi;
如果一个对象的属性本身就包含点(.)的键(self.ref),点操作符就无能为力了
var ref = {
id : "reference1",
func : function(){
return this.id;
}
};
var obj = {
id : "object1",
"self.ref" : ref
};
当我们尝试访问obj的”self.ref”这个属性的时候:obj.self.ref,解释器会以为obj中有个名为self的属性,而self对象又有个ref的属性,这样会发生不可预知的错误,一个好的解决方法是使用中括号([])运算符来访问:
obj[“self.ref”].func();
在这种情况下,中括号操作符成为唯一可行的方式,因此,建议在不知道对象的内部结构的时候(比如要遍历对象来获取某个属性的值),一定要使用中括号操作符,这样可以避免一些意想不到的bug。
当使用变量访问属性时使用中括号.
var luke = {
jedi: true,
age: 28
};
function getProp(prop) {
return luke[prop];
}
var isJedi = getProp('jedi');
总是使用 var
来声明变量,如果不这么做将导致产生全局变量,我们要避免污染全局命名空间。
// bad
superPower = new SuperPower();
// good
var superPower = new SuperPower();
使用一个 var
以及新行声明多个变量,缩进4个空格。
// bad
var items = getItems();
var goSportsTeam = true;
var dragonball = 'z';
// good
var items = getItems(),
goSportsTeam = true,
dragonball = 'z';
最后再声明未赋值的变量,当你想引用之前已赋值变量的时候很有用。
// bad
var i, len, dragonball,
items = getItems(),
goSportsTeam = true;
// bad
var i, items = getItems(),
dragonball,
goSportsTeam = true,
len;
// good
var items = getItems(),
goSportsTeam = true,
dragonball,
length,
i;
在作用域顶部声明变量,避免变量声明和赋值引起的相关问题。
// bad
function() {
test();
console.log('doing stuff..');
//..other stuff..
var name = getName();
if (name === 'test') {
return false;
}
return name;
}
// good
function() {
var name = getName();
test();
console.log('doing stuff..');
//..other stuff..
if (name === 'test') {
return false;
}
return name;
}
// bad
function() {
var name = getName();
if (!arguments.length) {
return false;
}
return true;
}
// good
function() {
if (!arguments.length) {
return false;
}
var name = getName();
return true;
}
===
和 !==
以及 ==
和 !=
.条件表达式的强制类型转换遵循以下规则:
''
则被计算为 false, 否则为 trueif ([0]) {
// true
// An array is an object, objects evaluate to true
}
使用快捷方式.
// bad
if (name !== '') {
// ...stuff...
}
// good
if (name) {
// ...stuff...
}
// bad
if (collection.length > 0) {
// ...stuff...
}
// good
if (collection.length) {
// ...stuff...
}
阅读 Truth Equality and JavaScript 了解更多
给所有多行的块使用大括号
// bad
if (test)
return false;
// good
if (test) return false;
// good
if (test) {
return false;
}
// bad
function() { return false; }
// good
function() {
return false;
}
使用 /** ... */
进行多行注释,包括描述,指定类型以及参数值和返回值
// bad
// make() returns a new element
// based on the passed in tag name
//
// @param <String> tag
// @return <Element> element
function make(tag) {
// ...stuff...
return element;
}
// good
/**
* make() returns a new element
* based on the passed in tag name
*
* @param <String> tag
* @return <Element> element
*/
function make(tag) {
// ...stuff...
return element;
}
使用 //
进行单行注释,在评论对象的上面进行单行注释,注释前放一个空行.
// bad
var active = true; // is current tab
// good
// is current tab
var active = true;
// bad
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
var type = this._type || 'no type';
return type;
}
// good
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
var type = this._type || 'no type';
return type;
}
如果你有一个问题需要重新来看一下或如果你建议一个需要被实现的解决方法的话需要在你的注释前面加上 FIXME
或 TODO
帮助其他人迅速理解
function Calculator() {
// FIXME: shouldn't use a global here
total = 0;
return this;
}
function Calculator() {
// TODO: total should be configurable by an options param
this.total = 0;
return this;
}
多行数组和元素初始化时,最好缩进两个空格。
// 对象初始化
var inset = {
top: 10,
right: 20,
bottom: 15,
left: 12
};
// 数组初始化
this.rows_ = [
'"Slartibartfast" <[email protected]>',
'"Zaphod Beeblebrox" <[email protected]>',
'"Ford Prefect" <[email protected]>',
'"Arthur Dent" <[email protected]>',
'"Marvin the Paranoid Android" <[email protected]>',
'[email protected]'
];
// 直接在方法中调用
goog.dom.createDom(goog.dom.TagName.DIV, {
id: 'foo',
className: 'some-css-class',
style: 'display:none'
}, 'Hello, world!');
尽可能的将所有的函数参数都写在同一行上,但为了保持增强可读性,如果一行超过了80字符的话可适当的换行,甚至可以每个参数都独立一行,记得格式上的优化,比如缩进4个空格和对齐括号。
// Four-space, wrap at 80. Works with very long function names, survives
// renaming without reindenting, low on space.
goog.foo.bar.doThingThatIsVeryDifficultToExplain = function(
veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
// ...
};
// Four-space, one argument per line. Works with long function names,
// survives renaming, and emphasizes each argument.
goog.foo.bar.doThingThatIsVeryDifficultToExplain = function(
veryDescriptiveArgumentNumberOne,
veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy,
artichokeDescriptorAdapterIterator) {
// ...
};
// Parenthesis-aligned indentation, wrap at 80. Visually groups arguments,
// low on space.
function foo(veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
// ...
}
// Parenthesis-aligned, one argument per line. Visually groups and
// emphasizes each individual argument.
function bar(veryDescriptiveArgumentNumberOne,
veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy,
artichokeDescriptorAdapterIterator) {
// ...
}
事实上,除了数组和元素的初始化和传递匿名方法以外,都应该相对于上一行表达式的左对齐缩进4个空格,而不是2个
someWonderfulHtml = '' +
getEvenMoreHtml(someReallyInterestingValues, moreValues,
evenMoreParams, 'a duck', true, 72,
slightlyMoreMonkeys(0xfff)) +
'';
thisIsAVeryLongVariableName =
hereIsAnEvenLongerOtherFunctionNameThatWillNotFitOnPrevLine();
thisIsAVeryLongVariableName = 'expressionPartOne' + someMethodThatIsLong() +
thisIsAnEvenLongerOtherFunctionNameThatCannotBeIndentedMore();
someValue = this.foo(
shortArg,
'Some really long string arg - this is a pretty common case, actually.',
shorty2,
this.bar());
if (searchableCollection(allYourStuff).contains(theStuffYouWant) &&
!ambientNotification.isActive() && (client.isAmbientSupported() ||
client.alwaysTryAmbientAnyways())) {
ambientNotification.activate();
}
二元和三元操作符
// 能放一行的都放在一行里
var x = a ? b : c;
// 缩进4个空格
var y = a ?
longButSimpleOperandB : longButSimpleOperandC;
// 缩进到第一个判断变量位置
var z = a ?
moreComplicatedB :
moreComplicatedC;
大括号前放一个空格
// bad
function test(){
console.log('test');
}
// good
function test() {
console.log('test');
}
// bad
dog.set('attr',{
age: '1 year',
breed: 'Bernese Mountain Dog'
});
// good
dog.set('attr', {
age: '1 year',
breed: 'Bernese Mountain Dog'
});
在做长方法链时使用缩进.
// bad
$('#items').find('.selected').highlight().end().find('.open').updateCount();
// good
$('#items')
.find('.selected')
.highlight()
.end()
.find('.open')
.updateCount();
// bad
var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true)
.attr('width', (radius + margin) * 2).append('svg:g')
.attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
.call(tron.led);
// good
var leds = stage.selectAll('.led')
.data(data)
.enter().append('svg:svg')
.class('led', true)
.attr('width', (radius + margin) * 2)
.append('svg:g')
.attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
.call(tron.led);
不要将逗号放前面
// bad
var once
, upon
, aTime;
// good
var once,
upon,
aTime;
// bad
var hero = {
firstName: 'Bob'
, lastName: 'Parr'
, heroName: 'Mr. Incredible'
, superPower: 'strength'
};
// good
var hero = {
firstName: 'Bob',
lastName: 'Parr',
heroName: 'Mr. Incredible',
superPower: 'strength'
};
不要加多余的逗号,这可能会在IE下引起错误,同时如果多一个逗号某些ES3的实现会计算多数组的长度。
// bad
var hero = {
firstName: 'Kevin',
lastName: 'Flynn',
};
var heroes = [
'Batman',
'Superman',
];
// good
var hero = {
firstName: 'Kevin',
lastName: 'Flynn'
};
var heroes = [
'Batman',
'Superman'
];
语句结束一定要加分号
// bad
(function() {
var name = 'Skywalker'
return name
})()
// good
(function() {
var name = 'Skywalker';
return name;
})();
// good
;(function() {
var name = 'Skywalker';
return name;
})();
字符串:
// => this.reviewScore = 9;
// bad
var totalScore = this.reviewScore + '';
// good
var totalScore = '' + this.reviewScore;
// bad
var totalScore = '' + this.reviewScore + ' total score';
// good
var totalScore = this.reviewScore + ' total score';
对数字使用 parseInt
并且总是带上类型转换的基数.
var inputValue = '4';
// bad
var val = new Number(inputValue);
// bad
var val = +inputValue;
// bad
var val = inputValue >> 0;
// bad
var val = parseInt(inputValue);
// good
var val = Number(inputValue);
// good
var val = parseInt(inputValue, 10);
// good
/**
* parseInt was the reason my code was slow.
* Bitshifting the String to coerce it to a
* Number made it a lot faster.
*/
var val = inputValue >> 0;
布尔值:
var age = 0;
// bad
var hasAge = new Boolean(age);
// good
var hasAge = Boolean(age);
// good
var hasAge = !!age;
account-model.js
避免单个字符名,让你的变量名有描述意义。
// bad
function q() {
// ...stuff...
}
// good
function query() {
// ..stuff..
}
当命名对象、函数和实例时使用驼峰命名规则
// bad
var OBJEcttsssss = {};
var this_is_my_object = {};
var this-is-my-object = {};
function c() {};
var u = new user({
name: 'Bob Parr'
});
// good
var thisIsMyObject = {};
function thisIsMyFunction() {};
var user = new User({
name: 'Bob Parr'
});
当命名构造函数或类时使用驼峰式大写
// bad
function user(options) {
this.name = options.name;
}
var bad = new user({
name: 'nope'
});
// good
function User(options) {
this.name = options.name;
}
var good = new User({
name: 'yup'
});
命名私有属性时前面加个下划线 _
// bad
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
// good
this._firstName = 'Panda';
当保存对 this
的引用时使用 _this
.
// bad
function() {
var self = this;
return function() {
console.log(self);
};
}
// bad
function() {
var that = this;
return function() {
console.log(that);
};
}
// good
function() {
var _this = this;
return function() {
console.log(_this);
};
}
如果你确实有存取器函数的话使用getVal() 和 setVal(‘hello’)
// bad
dragon.age();
// good
dragon.getAge();
// bad
dragon.age(25);
// good
dragon.setAge(25);
如果属性是布尔值,使用isVal() 或 hasVal()
// bad
if (!dragon.age()) {
return false;
}
// good
if (!dragon.hasAge()) {
return false;
}
可以创建get()和set()函数,但是要保持一致
function Jedi(options) {
options || (options = {});
var lightsaber = options.lightsaber || 'blue';
this.set('lightsaber', lightsaber);
}
Jedi.prototype.set = function(key, val) {
this[key] = val;
};
Jedi.prototype.get = function(key) {
return this[key];
};
给对象原型分配方法,而不是用一个新的对象覆盖原型,覆盖原型会使继承出现问题。
function Jedi() {
console.log('new jedi');
}
// bad
Jedi.prototype = {
fight: function fight() {
console.log('fighting');
},
block: function block() {
console.log('blocking');
}
};
// good
Jedi.prototype.fight = function fight() {
console.log('fighting');
};
Jedi.prototype.block = function block() {
console.log('blocking');
};
方法可以返回 this
帮助方法可链。
// bad
Jedi.prototype.jump = function() {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
};
var luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20) // => undefined
// good
Jedi.prototype.jump = function() {
this.jumping = true;
return this;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
return this;
};
var luke = new Jedi();
luke.jump()
.setHeight(20);
可以写一个自定义的toString()方法,但是确保它工作正常并且不会有副作用。
function Jedi(options) {
options || (options = {});
this.name = options.name || 'no name';
}
Jedi.prototype.getName = function getName() {
return this.name;
};
Jedi.prototype.toString = function toString() {
return 'Jedi - ' + this.getName();
};
当给事件附加数据时,传入一个哈希而不是原始值,这可以让后面的贡献者加入更多数据到事件数据里而不用找出并更新那个事件的事件处理器
// bad
$(this).trigger('listingUpdated', listing.id);
...
$(this).on('listingUpdated', function(e, listingId) {
// do something with listingId
});
更好:
// good
$(this).trigger('listingUpdated', { listingId : listing.id });
...
$(this).on('listingUpdated', function(e, data) {
// do something with data.listingId
});
!
开始,这保证了如果一个有问题的模块忘记包含最后的分号在合并后不会出现错误总是在模块顶部声明 'use strict';
// fancyInput/fancyInput.js
!function(global) {
'use strict';
var previousFancyInput = global.FancyInput;
function FancyInput(options) {
this.options = options || {};
}
FancyInput.noConflict = function noConflict() {
global.FancyInput = previousFancyInput;
return FancyInput;
};
global.FancyInput = FancyInput;
}(this);
缓存jQuery查询
// bad
function setSidebar() {
$('.sidebar').hide();
// ...stuff...
$('.sidebar').css({
'background-color': 'pink'
});
}
// good
function setSidebar() {
var $sidebar = $('.sidebar');
$sidebar.hide();
// ...stuff...
$sidebar.css({
'background-color': 'pink'
});
}
$('.sidebar ul')
或 $('.sidebar ul')
,jsPerf对有作用域的jQuery对象查询使用 find
// bad
$('.sidebar', 'ul').hide();
// bad
$('.sidebar').find('ul').hide();
// good
$('.sidebar ul').hide();
// good
$('.sidebar > ul').hide();
// good (slower)
$sidebar.find('ul');
// good (faster)
$($sidebar[0]).find('ul');
with 非特殊业务, 禁用!!!
======================================================
###参考
Github中watch、star、fork的如何用?
看到某人的repository,其实如果觉得有帮助,可以 star 或者 watch, 如果 fork 到你的 repositories 下则不能保证你的 repo 是最新的,除非是主动定期的 pull。
请选择合理的方式。更多详见 Github 帮助文档
您可以在 SVG 文档中包括预定义的内容 —— 在呈现的文档内或文档之外定义的内容。
#引用内部绘图 symbol,defs 都可以事先定义好图形,而后use来引用
<svg width="200" height="200" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="shape2">
<circle cx="25" cy="25" r="25"></circle>
<title>My image</title>
</symbol>
<defs>
<g id="shape3">
<circle cx="25" cy="25" r="25" fill="red"></circle>
</g>
</defs>
<use xlink:href="#shape2" x="50" y="25" ></use>
<use xlink:href="#shape3" x="150" y="25" ></use>
</svg>
有关symbol,defs的异同点,可以参考这篇文章
#引用外部绘图 我们事先已经准备好了一个外部绘图svg文件svg-file-test.svg
##1.使用<image> 使用预定义内容作为 SVG 绘图一部分的方法之一是使用 <image>元素。在概念上,SVG 中的<image>与 HTML 中的 <img>非常类似:该元素只须指示呈现客户机在当前的 SVG 环境中绘制外部图像的内容 —— 其本身可能是 SVG 或者是 JPEG 或 PNG 格式的光栅图像。您几乎可以像调整一个规则的图形元素那样来调整外部图像的大小和改变其位置
<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="0" y="0" width="300" height="200" xlink:href="../assets/img/svg-file-test.svg"></image>
<image x="0" y="200" width="300" height="200" xlink:href="../assets/img/wl_white.png"></image>
</svg>
##2.使用<use>元素 任何svg, symbol, g, 单个的图形元素和use元素本质上都可以作为模板对象被use元素引用(例如初始化)。use引用的图形内容会在指定的位置渲染。与image元素不同,use元素不能引用整个文档。
<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<use xlink:href="../assets/img/svg-file-test.svg#svg2" x="0" y="0" width="100" height="100" ></use>
<use xlink:href="../assets/img/svg-file-test.svg#rect2985" x="0" y="325" width="300" height="200" ></use>
</svg>
第一个use引用了该文件的整个svg元素。
第二个use引用了该文件的rect元素。
ECMAScript5中引入的严格模式,通过让JavaScript运行环境对一些开发过程中最常见和不易发现的错误做出和当前不同的处理,来让开发者拥有一个”更好”的JavaScript语言。很长一段时间内,由于只有Firefox支持严格模式,我曾对严格模式表示怀疑。但到了今天,所有主流的浏览器都在他们的最新版本中支持了严格模式(包括IE10,Opera12和Android4,IOS5)是时候开始使用严格模式了。
严格模式为JavaScript引入了很多变化,我把他们分为两类(明显的和细微的)。细微改进的目标是修复当前JavaScript中的一些细节问题,对于这些问题我不在这里进行深入介绍;如果你有兴趣,请阅读Dmitry Soshnikov撰写的精彩文档ECMA-262-5 in Detail Chapter 2 Strict Mode。 我在这里主要介绍严格模式引入的明显变化,那些在你使用严格模式前应该知道的概念和那些对你帮助最大的改变。
在开始学习具体特性前,请记住严格模式的一大目标是让你能更快更方便的调试
。运行环境在发现问题时显性的抛出错误比默不做声的失败或怪异行事(未开启严格模式的JavaScript运行环境经常这样)要好。严格模式会抛出更多错误,但这是好事,因为这些错误会唤起你注意并修复很多以前很难被发现的潜在问题。
首先,严格模式中去除了with语句,包含with语句的代码在严格模式中会抛出异常。所以使用严格模式的第一步:确保你的代码中没有使用with。
// 在严格模式中以下JavaScript代码会抛出错误
with (location) {
alert(href);
}
其次,局部变量在赋值前必须先进行申明。在启用严格模式之前,为一个未申明的局部变量复制时会自动创建一个同名全局变量。这是Javacript程序中最容易出现的错误之一, 在严格模式中尝试这么做时会有显性的异常抛出。
// 严格模式下会抛出异常
(function() {
someUndeclaredVar = "foo";
}());
严格模式中另一个重要的变化是函数中未被定义或为空( null or undefined)的this不在默认指向全局环境(global)。这会造成一些依赖函数中默认this行为的代码执行出错,例如:
window.color = "red";
function sayColor() {
alert(this.color);
}
// 在strict模式中会报错, 如果不在严格模式中则提示 “red"
sayColor();
// 在strict模式中会报错, 如果不在严格模式中则提示 “red"
sayColor.call(null);
this在被赋值之前会一直保持为undefined,这意味着当一个构造函数在执行时,如果之前没有明确的new关键词,会抛出异常。
function Person(name) {
this.name = name;
}
//在严格模式中会报错
var me = Person("Nicholas");
在上面的代码中,Person构造函数运行时因为之前没有new,函数中的this会保留为undefined, 由于你不能为undefined设置属性,上面的代码会抛出错误。 在非strict模式环境中,没有被复制的this会默认指向window全局变量,运行的结果将是意外的为window全局变量设置name属性。
当编写大量代码时,对象属性和函数参数很容易一不小心被设置成一个重复的名字。严格模式在这种情况下会显性的抛出错误
//重复的变量名,在严格模式下会报错
function doSomething(value1, value2, value1) {
//code
}
//重复的对象属性名,在严格模式下会报错:
var object = {
foo: "bar",
foo: "baz"
};
以上的代码在严格模式中都会被认为是语法错误而在执行前就让你能得到提示。
虽然eval()语句最终没有被移除,但在严格模式中仍然对它进行了一些改进。最大的改变是在eval()中执行的变量和函数申明不会直接在当前作用域中创建相应变量或函数,例如:
(function() {
eval("var x = 10;");
// 非严格模式中,alert 10
// 严格模式中则因x未被定义而抛出异常,
alert(x);
}());
任何在eval()执行过程中创建的变量或者函数保留在eval()中。但你能明确的从eval()语句的返回值来获取eval()中的执行结果,例如:
(function() {
var result = eval("var x = 10, y = 20; x + y");
// 在strict或非strict模式中都能正确的运行余下的语句.(resulst为30)
alert(result);
}());
ECMAScript5中还引入为对象的特定属性设为只读,或让整个对象不可修改的能力。 但在非严格模式中,尝试修改一个只读属性只会默不做声的失败。 在你和一些浏览器原生API打交道过程中,你很可能遇到这种情况。严格模式会在这种情况下明确的抛出异常,提醒你修改这个属性是不被允许的。
var person = {};
Object.defineProperty(person, "name" {
writable: false,
value: "Nicholas"
});
// 在非严格模式时,沉默的失败,在严格模式则抛出异常.
person.name = "John"; 上面的例子中,name属性被设为只读,非严格模式中执行对name属性的修改不会引发报错,但修改不会成功。但严格模式则会明确的抛出异常。
NOTE: 强烈建议你在使用任何ECMAScript属性特性指定时开启严格模式。
在现代浏览器中开启严格模式非常容易,只需要在JavaScript代码中出现以下指令即可
"use strict";
虽然看上去上面的代码仅仅只是未赋予某个变量的字符串,它实际上起到指示JavaScript引擎切换到严格模式的作用(不支持严格模式的浏览器会忽略以上代码,不会对后续的执行产生任何影响)。虽然你能把这个指令作用到全局或某个函数中,但这里还是要提醒,不要在全局环境下启用严格模式。
// 请不要这么使用
"use strict";
function doSomething() {
// 这部分代码会运行于严格模式
}
function doSomethingElse() {
// 这部分代码也会运行于严格模式
}
虽然上面的代码看起来不算一个大问题。但当你不负责维护页面中引入的全部代码时,这样使用strict模式会让你面临由于第三方代码没有为严格模式做好准备而引发的问题。 因此,最好把开启严格模式的指令作用于函数中,例如:
function doSomething() {
"use strict";
// 这个函数中的代码将会运行于严格模式
}
function doSomethingElse() {
// 这个函数中代码不会运行于严格模式
}
如果你想让严格模式在不止一个函数中开启,请使用立即执行函数表达式
(immediately-invoked function expression ,IIFE):
(function() {
"use strict";
function doSomething() {
// 这个函数运行于严格模式
}
function doSomethingElse() {
// 这个函数同样运行于严格模式
}
}());
我强烈建议你从现在开始就启用JavaScript严格模式,它能帮你发现代码中未曾注意到的错误。不要在全局环境中启用,但你能尽量多的使用IIFE(立即执行函数表达式)来把严格模式作用到多个函数范围内。一开始,你会遇到之前未曾碰到过的错误提示,这是正常的。当启用严格模式后,请确保在支持的浏览器中做了测试,以发现新的潜在问题。一定不要仅仅在代码中添加一行”use strict”就假定余下的代码能正常工作。最后,请在严格模式下开始编写更好的代码。
这里有各款浏览器对严格模式支持情况的一个汇总。
可以在这个页面对当前浏览器的严格模式支持度进行测试。
SVG Viewport和View Box用来设置图像的可见部分的尺寸。
##Viewport(视口) Viewport:视口,视觉窗口,是SVG图像的可见区域。SVG图像逻辑上是能显示你想要的宽和高,但实际上同一时间仅图像的某一部分是可见的。该可见的区域被称为Viewport。
您可以通过<svg>元素的width
和height
指定使用的Viewport宽度和高度的下面是一个例子:
<svg width="500" height="300"></svg>
这例子定义了一个Viewport,500个单位宽和300个单位高。
##坐标单位 如果你不指定任何内部宽度和高度属性的单位,单位都假定为像素。即,宽度500表示500个像素的宽度。
除了像素,还可以使用下面的单位:
单位 | 描述 |
---|---|
em | 默认字体大小 ,通常是一个字符高度 |
ex | x字符的高度 |
px | 像素 |
pt | 点(一英寸的1/72) |
pc | 派卡(一英寸的1/6) |
cm | 厘米 |
mm | 毫米 |
in | 英寸 |
在<svg>元素里面设置单位只会影响的<svg>的大小(即Viewport)。在SVG图像中显示的SVG图形的大小由你对每个图形设置的单位决定。如果没有指定单位,各单位将默认为像素。
下面是一个例子:
<svg width="10cm" height="10cm">
<rect x="50" y="100" width="50" height="50"
style="stroke: #000000; fill: none;"/>
<rect x="100" y="100" width="50mm" height="50mm"
style="stroke: #000000; fill: none;" />
</svg>
该<svg>图像有其单位设置为厘米。两个<rect>元素都有自己的单位设置。一个使用像素(没有单位明确设定),另一个使用毫米。
这里是所得到的图象,右边的(单位毫米)大于左边(单位像素)。
##View Box
您可以重新在<svg>元素内部定义没有单位的坐标,通过viewBox
属性来实现。下面是一个例子:
<svg width="500" height="200" viewBox="0 0 50 20" style="border: 1px solid #234567;">
<rect x="20" y="10" width="10" height="5"
style="stroke: #000000; fill:none;"/>
</svg>
此示例创建一个<svg>为500像素宽和200像素高,宽度元素的的viewBox
属性包含四个坐标。这些坐标就定义了<svg>的viewBox
属性。
在这种情况下,View Box跨度从0,0到50,20。这意味着,500 x 200像素 <svg>元素内部使用一个坐标系,它从0,0 到50,20。换言之,图形中使用的坐标,每1个单位,在<svg>对应于宽度500/50 = 10个像素,而在高200/20 = 10个像素。这就是为什么x轴为20及y轴为10的位置的矩形是真正位于(200,100),其宽度(10)和高度(5)对应于100个像素和50个像素。
另一种方式来解释它,viewBox
属性的前两个坐标定义的是<svg>左上角的用户坐标,后两个坐标定义的是<svg>右下角的用户坐标。该<svg>内部的空间被解释为从左上角坐标到右下角坐标跨越。
这里是所得到的图象:
注意<rect>里面的所有坐标元素1个单位就代表10像素。
##preserveAspectRatio保持宽高比 如果Viewport和View Box不具有相同的宽高比(宽度与高度之比),您需要指定SVG显示器(例如浏览器)如何显示SVG图像。使用<svg>的preserveAspectRatio属性。
该preserveAspectRatio属性需要用空格分隔的两个值。第一个值将告诉您View Box如何在Viewport中对齐。这个值本身就是两部分组成。第二个值将告诉您宽高比如何将被保留(如果有的话)。
第一个值指定的对齐由两部分组成。第一部分指定的x对齐和第二部分指定的y对齐。这里是x轴和y取向的值的列表:
值 | 描述 |
---|---|
xMin | 对齐View Box最小x轴的值与Viewport的左边缘。 |
xMid | 对齐View Box的x轴的中心与Viewport的中心x轴坐标。 |
xMax | 对齐View Box最大x轴的值与Viewport的右边缘。 |
YMin | 对齐View Box最小y轴的值与Viewport的顶部边缘。 |
YMid | 对齐View Box的y轴的中心与Viewport的中心y轴坐标。 |
YMin | 对齐View Box最大y轴的值与Viewport的底部边缘。 |
这里有两个例子:
xMaxYMax
xMidYMid
在preserveAspectRatio第二部分属性值可以采取三种不同的值:
值 | 描述 |
---|---|
meet | 保持宽高比和比例视图框,以适应内视口。 |
slice | 保留宽高比,任何不适合Viewport宽高比的图像的会被切掉。 |
none | 不保留宽高比。缩放图像以View Box充满完全适应Viewport。比例会被扭曲。 |
在第二部分preserveAspectRatio属性值附加到第一部分,以空格分隔。这里有两个例子:
preserveAspectRatio="xMidYMid meet"
preserveAspectRatio="xMinYMin slice"
下面的实施例都具有宽度为500,高度为75和的viewBox属性设为0 0 250 75。这意味着,沿x轴的每个坐标单元将对应于2个像素,而是沿着Y轴的每个坐标单位只对应1个像素。在x轴缩放比为500/250=2 ,y轴的缩放比为75/75=1。这可能会导致一个扭曲,但我们会在下面的例子查看如何设置各种preserveAspectRatio。
SVG 中<line>并没有箭头,可以通过<marker>进行扩展。
先定义一个箭头
<defs>
<marker id="markerArrow" markerWidth="13" markerHeight="13" refx="2" refy="6" orient="auto">
<path d="M2,2 L2,11 L10,6 L2,2" style="fill: #000000;" />
</marker>
</defs>
其中orient="auto"
设置箭头的方向为自动适应线条的方向。
而后,画line ,line的marker-end
引用上面定义好的markerArrow
即可
<line x1="0" y1="0" x2="100" y2="50" stroke="red" stroke-width="1" marker-end="url(#markerArrow)" />
也可以应用在path中, 效果如下:
完整代码如下:
<svg width="500" height="100">
<defs>
<marker id="markerCircle" markerWidth="8" markerHeight="8" refx="5" refy="5">
<circle cx="5" cy="5" r="3" style="stroke: none; fill:#000000;"/>
</marker>
<marker id="markerArrow" markerWidth="13" markerHeight="13" refx="2" refy="6" orient="auto">
<path d="M2,2 L2,11 L10,6 L2,2" style="fill: #000000;" />
</marker>
</defs>
<line x1="0" y1="0" x2="100" y2="50" stroke="red" stroke-width="1" marker-end="url(#markerArrow)" />
<path d="M100,10 L150,10 L150,60"
style="stroke: #6666ff; stroke-width: 1px; fill: none;
marker-start: url(#markerCircle);
marker-mid:url(#arrow);
marker-end: url(#markerArrow) "
/>
</svg>
SVG 做地图具有可以任意比例放大缩小不失真的优点。本例基于d3.js的svg制作。
地图数据用GeoJSON存储。GeoJSON 是基于JSON 的、为Web 应用而编码地理数据的一个标准。实际上,GeoJSON 并不是另一种格式,而只是JSON 非常特定的一种使用方法。
网上有很多免费的GeoJSON下载,本例子中国地图GeoJSon 可以从本例源码 下载
###1.获取d3
在项目中引入即可,
<script src="http://d3js.org/d3.v3.min.js"></script>
###2.创建svg var width = 960, height = 500; var svg = d3.select(“body”) .append(“svg”) .attr(“width”, width) .attr(“height”, height); ###3.创建投影(projection) var projection = d3.geo.mercator().translate([width / 2, height / 2]).center([105, 38]).scale(550);
###4.创建path var path = d3.geo.path().projection(projection);
###5. 解析json d3.json(“china.geo.json”, function(json) {
svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.on('mouseover', function(data) {
d3.select(this).attr('fill', 'rgba(2,2,139,0.61)');
//创建显示tooltip用的矩形
svg.append("rect")
.attr("id", "tooltip1")
.attr("x", 50)
.attr("y",50)
.attr("width",140)
.attr("height",130)
.attr("stroke","black")
.attr("fill","none")
;
//创建显示tooltip文本
svg.append("text")
.attr("id", "tooltip2")
.attr("x", 100)
.attr("y", 100)
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("font-weight", "bold")
.attr("fill", "black")
.text(data.properties.name);
})
.on('mouseout', function(data) {
d3.select(this).attr('fill', 'rgba(128,124,139,0.61)');
//Remove the tooltip
d3.select("#tooltip1").remove();
d3.select("#tooltip2").remove();
})
.attr('fill', 'rgba(128,124,139,0.61)')
.attr('stroke', 'rgba(255,255,255,1)')
.attr('stroke-width', 1)
;
});
演示效果:
##安装svn 1下载SlikSVN
2安装
我的是在D:\Program Files\SlikSvn
目录下
3.在WebStorm中配置
file->settings->Version Contorl->subversion->with conmand line client
设置成你的D:\Program Files\SlikSvn\bin\svn.exe
##svn共享项目 1.share Project
2.select target
3.验证
4.确认
##svn检出项目 1.选择项目
2.检出
##相关问题的解决 如果遇到如下错误 “Cannot load supported formats: Cannot run program ‘svn’: CreateProcess error=2, ” 请回到最上面,进行“安装svn”这步骤
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400" height="200" >
<script>
function lineGClick(evt) {
var lineA = document.getElementById("lineA");
if( lineA.getAttribute("display")=="none"){
lineA.setAttribute("display","#000000");
line2.setAttribute("display","none");
}else{
lineA.setAttribute("display","none");
line2.setAttribute("display","#000000");
}
}
</script>
<defs>
<g id="lineG1" >
<line id="line1" fill="none" stroke="#000000" stroke-width="4" x1="10" y1="10" x2="10" y2="40"/>
<line id="lineA" fill="none" display="none" stroke="#000000" stroke-width="4" x1="10" y1="40" x2="10" y2="70"/>
<line id="line2" fill="none" stroke="#000000" stroke-width="4" x1="10" y1="40" x2="35" y2="60"/>
<line id="lineB" fill="none" stroke="#000000" stroke-width="4" x1="10" y1="70" x2="10" y2="100"/>
</g>
</defs>
<text x="10" y="20" fill="red">一个SVG电力开关的例子。点击开关,进行状态转换</text>
<use x="10" y="30" xlink:href="#lineG1" onclick="lineGClick(evt)"/>
<a xlink:href="http://www.waylau.com" target="_blank">
<text x="10" y="180" fill="red">欢迎访问wwww.waylau.com</text>
</a>
</svg>
效果:
解释:
defs
标签定义了可以重复利用的组件
use
引用了defs
所定义的组件,其中onclick
监听了鼠标点击事件
##1.百度相册外链分享
优点:国内站,速度快,可以批量上传
缺点:右下角会有水印,很是不爽
##2.试下Photobucket 免费,无水印
优点:可以批量上传,可以照片分类,文件夹下可以再建文件夹 缺点:国外网站,网速比较慢
##3.POCO貌似也不错 POCO是您的图片生活记录和分享平台,在这里用图片记录您的生活、分享您的一切,在各兴趣社区以图会友、参加各种POCO线上线下活动。 POCO给你提供。。。。 1.跟图片有关的一切服务:发单图微博、发组图博文、发兴趣图片、建立免费可外链相册… 2.视觉图片达人必备的、互联网最创造力的个人空间 3.图片生活分享交流社区(摄影、美食、宠物、达物、旅游、手机拍客、模特….),您的优秀图片分享将有机会登上 POCO网站首页,并获得荣誉勋章 4.获得POCO优质生活体验(美食菜谱、餐厅搜索及优惠、旅游景点大全、相机图片欣赏等)
需要注意的是如果直接复制图片地址,无法正常显示的话,如下: 原地址:
将图片地址进行修改:
<img src="http://image16-c.poco.cn/mypoco/myphoto/20140523/11/17476175320140523113816047.png"/>
将-c
去掉即可
<img src="http://image16.poco.cn/mypoco/myphoto/20140523/11/17476175320140523113816047.png"/> 修改地址后的图片 <img src="http://image16.poco.cn/mypoco/myphoto/20140523/11/17476175320140523113726012.png?280x280_130"/>
个人昵称水印
社区水印
缺点:只能单张图片上传
##4.七牛云存储 优点:国内站,稳定,全网加速,图片处理:
缺点:有流程和存储的限制。体验用户:储存空间1GB每月Put请求1万次每月下载流量1GB每月Get请求10万次创建1个空间仅支持富媒体上传. 如果注册为标准用户,还要提供身份,个人照片,貌似有点麻烦
##5.爱唯侦察出的图床http://99btgc01.info/
方便上传电影的封面,听站长说还算稳定。操作也简单,无需管理
从5.5版本开始,Jaspersoft Studio将取代iReport 成为JasperReports官方设计器。iReport 维护截止日期到2015年底,意味着不会再有新的功能增加进iReport,但会做一些关键bug的修复、更新。所幸的是基于eclipse的Jaspersoft Studio同样开源、免费!Yeah!
Jaspersoft Studio是一个专为JasperReports报表引擎而开发的报表设计器,是iReport设计器的一个完整重构,基于Eclipse平台实现。它能够让你创建包含图表、图片、子报表、交叉表等非常复杂的布局。可以通过JDBC、TableModels、JavaBeans、XML、Hibernate、CSV或自定义数据源来读取数据。可以将报表输出成PDF、RTF、XML、XLS、CSV、HTML、XHTML、text、DOCX或OpenOffice。
##Report Life Cycle(报表生命周期) iReport和JasperSoft Studio中的报表的生命周期是相同的。
当你使用iReport或JasperSoft Studio做报表时,要创建一个JRXML文件,该文件是包含报表布局定义的XML文档。布局是完全可视化,这样你就可以忽略JRXML文件的基础结构。执行报告之前,JRXML必须编译成名为Jasper的二进制文件。Jasper文件就是应用程序生成报表所需要的。
有许多数据源类型。您可以从SQL查询,XML文件,csv文件,HQL(Hibernate查询语言)查询,JavaBeans集合等。如果你没有一个合适的数据源,JasperReports的允许你编写自己的自定义数据源。通过Jasper文件和数据源,JasperReports 就能生成最终用户想要的文档格式。
iReport和JasperSoft Studio允许您配置数据源,并使用它们来测试您的报表。在许多情况下,数据驱动向导可以帮助您快速设计您的报表。iReport包括JasperReports引擎本身,可以让您预览报表输出,测试和优化您的报表。
##User Interface(用户界面) JasperSoft Studio 有两个不同的版本:一个独立的RCP产品,以及Eclipse插件的版本。熟悉Eclipse的人都会对用户界面感到很熟悉,而那些新用户,或者那些只熟悉iReport的设计师,则会觉得显示元素的布局会出现很大的不同。独立和插件的版本也有类似的用户界面。在下面可以看到包括JasperSoft Studio界面的预览:
Report editing area(主编辑区域)中,您直观地通过拖动,定位,对齐和通过Designer palette(设计器调色板)对报表元素调整大小。
JasperSoft Studio有一个多标签编辑器,Design,Source和 Preview:
很多页面可以查看数据:
最后,Report state summary提供了有关在报表编译/填充/执行统计用户有用的信息。错误会显示在这里。
下面是一个简短的比较表,帮助用户看到iReport和JasperSoft Studio的主要内容。
iReport Designer | Jaspersoft Studio |
---|---|
JasperServer Repository | Repository Explorer |
Report Inspector | Outline view |
Report Designer | Report Editing Area |
Problems List | Problems view |
Elements palette | Designer Palette |
Formatting tools | Available via context menu on the element |
Property sheet | Properties view |
Styles library | — |
— | Project Explorer |
iReport Designer Output window | Report State summary |
参考:http://community.jaspersoft.com/wiki/introduction-jaspersoft-studio http://community.jaspersoft.com/project/ireport-designer
#SVG动画示例 下面是一个简单的SVG动画的例子:
<svg width="500" height="100">
<rect x="10" y="10" height="110" width="110"
style="stroke:#ff0000; fill: #0000ff">
<animateTransform
attributeName="transform"
begin="0s"
dur="20s"
type="rotate"
from="0 60 60"
to="360 60 60"
repeatCount="indefinite"
/>
</rect>
</svg>
注意到,<rect>元素有一个<animateTransform>嵌套在它里面。正是这种元素驱动了矩形。
#动画选项的概述
动画是通过操纵图形随时间变化的属性而进行的。用下面5个SVG动画元素的 一个或多个来完成的:
这些动画元素在整个这段文字的后面要谈到的。
##set
<set>元素是最简单的SVG动画元素。j简单地将一个属性修改成一定值后,特定时间间隔过后就能能效了。因此,该图形是不连续的动画,只是改变属性值一次。
这里是一个<set>元素的例子:
<svg width="500" height="100">
<circle cx="30" cy="30" r="25" style="stroke: none; fill: #0000ff;">
<set attributeName="r" attributeType="XML"
to="100"
begin="5s" />
</circle>
</svg>
注意<set>嵌套在circle里面。这就是<set>元素的用法。
该<set>元素将时间设置成一个属性的值。设置属性的名称是指定的attributeName。修改成的值为to。开始生效的时间间隔为begin。
上面的例子中的属性设置r 5秒后为100。
##attributeType
在前面的例子也有一个attributeType属性在<set>元素里面。该值设置为XML。因为SVG的<circle >元素素是XML元素。
也可以将attributeType属性设置为CSS。
<svg width="400" height="400">
<rect x="20" y="20" width="250" height="250" style="fill:blue">
<animate attributeType="CSS" attributeName="opacity" from="1" to="0" dur="5s" repeatCount="indefinite" />
</rect>
Sorry, your browser does not support inline SVG.
</svg>
如果你不提供一个attributeType属性,那么浏览器会尝试猜测是一个XML属性还是CSS属性。
##animate
该animate元素被用来驱动SVG图形的属性。下面是一个例子:
<svg width="500" height="75">
<circle cx="30" cy="30" r="25" style="stroke: none; fill: #0000ff;">
<animate attributeName="cx" attributeType="XML"
from="30" to="470"
begin="0s" dur="5s"
fill="remove" repeatCount="indefinite"/>
</circle>
</svg>
这个例子中的<circle>元素cx的属性从30改成了479。动画从0秒开始,并具有5秒持续时间。
当动画完成,animate的属性被设置回其原始值(fill=”remove”)。如果想要的将动画属保持在to值的位置,则fill设置为“freeze”。动画如果无限重复则设置repeatCount的值。
##animateColor
<svg width="500" height="80">
<circle cx="30" cy="30" r="25" style="stroke: none; fill: #0000ff;">
<animateColor attributeName="fill"
from="#0000ff" to="#ff0000"
begin="0s" dur="5s"
fill="freeze" repeatCount="indefinite"/>
</circle>
</svg>
这个例子中的动画填写将CSS属性从颜色#0000FF(蓝色)的颜色转为#FF0000(红色)。
注: 尽管SVG定义了”animateColor”,但是它已经被弃用了,替代它的是”animate”元素。
##animateTransform
<animateTransform>元素可以驱动图形的transform&的属性。而<animate>元素不能做到这一点。 下面是一个例子:
<svg width="500" height="200">
<rect x="20" y="20" width="100" height="40"
style="stroke: #ff00ff; fill: none;" >
<animateTransform attributeName="transform"
type="rotate"
from="0 100 100" to="360 100 100"
begin="0s" dur="10s"
repeatCount="indefinite"
/>
</rect>
<circle cx="100" cy="100" r="2" style="stroke: none; fill: #0000ff;"/>
</svg>
本例中在点(100,100)位置从0至360度进行旋绕。
下面是比例尺放大的示例:
<svg width="500" height="200">
<rect x="20" y="20" width="40" height="40"
style="stroke: #ff00ff; fill: none;" >
<animateTransform attributeName="transform"
type="scale"
from="1 1" to="2 3"
begin="0s" dur="10s"
repeatCount="indefinite"
/>
</rect>
</svg>
##animateMotion
该<animateMotion>元素可以驱动图形沿着一条路径运动。下面是一个例子:
<svg width="500" height="150">
<path d="M10,50 q60,50 100,0 q60,-50 100,0"
style="stroke: #000000; fill: none;"
/>
<rect x="0" y="0" width="30" height="15"
style="stroke: #ff0000; fill: none;">
<animateMotion
path="M10,50 q60,50 100,0 q60,-50 100,0"
begin="0s" dur="10s" repeatCount="indefinite"
/>
</rect>
</svg>
为了以配合道路的坡度,设置了rotate=”auto”。下面是一个例子:
<svg width="500" height="150">
<path d="M10,50 q60,50 100,0 q60,-50 100,0"
style="stroke: #000000; fill: none;"
/>
<rect x="0" y="0" width="30" height="15"
style="stroke: #ff0000; fill: none;">
<animateMotion
path="M10,50 q60,50 100,0 q60,-50 100,0"
begin="0s" dur="10s" repeatCount="indefinite"
rotate="auto"
/>
</rect>
</svg>
##Time Units(时间单位)
时间单位经常用在begin,dur和end的属性值中,“5s”表示”5秒”。
单位 | 描述 |
---|---|
h | Hours(时) |
min | Minutes(分) |
s | Seconds(秒) |
ms | Milliseconds(毫秒) |
也可以是这种hh:mm:ss
这种格式,比如1:30:45
表示时间长度为”1小时30分钟45秒”。
##Coordinating Animations(协调动画)
<svg width="500" height="100">
<rect x="0" y="0" width="30" height="15"
style="stroke: #ff0000; fill: none;">
<animate id="one"
attributeName="x" attributeType="XML"
from="0" to="400"
begin="0s" dur="10s" fill="freeze"
/>
<animate
attributeName="y" attributeType="XML"
from="0" to="80"
begin="one.end" dur="10s" fill="freeze"
/>
</rect>
</svg> 一个动画的开始时间是另外一个动画的结束时间。
也可以通过设置时间的偏移量 one.begin+10s one.end+5s
另外,你可以在一个动画指定一个明确的结束时间end属性。这并不能取代dur属性。它所做的是添加另一种可能结束一个动画,所以以先到为准。下面是一个例子:
<animate
attributeName="y" attributeType="XML"
from="0" to="50"
begin="one.begin+3s" dur="10s" end="one.end"
fill="freeze"
/>
该动画将有10秒的持续时间,或与one动画一起停止结束,以先到那个为准。
##Repeating Animations(重复动画)
重复动画可以用动画元素中的两个属性。
<svg width="500" height="100">
<rect x="10" y="10" width="40" height="20"
style="stroke: #000000; fill: none;">
<animate attributeName="x" attributeType="XML"
from="10" to="400"
begin="0s" dur="10s"
repeatCount="indefinite"
/>
<animate attributeName="y" attributeType="XML"
from="10" to="100"
begin="0s" dur="10s"
fill="freeze"
repeatCount="indefinite"
/>
</rect>
</svg>
##Combining Animations(结合动画)
动画可以组合起来用,这里是一个例子:
<svg width="500" height="100">
<rect x="10" y="10" width="40" height="20"
style="stroke: #000000; fill: none;">
<animate attributeName="x" attributeType="XML"
from="10" to="400"
begin="0s" dur="10s"
repeatCount="indefinite"
/>
<animate attributeName="y" attributeType="XML"
from="10" to="100"
begin="0s" dur="10s"
fill="freeze"
repeatCount="indefinite"
/>
</rect>
</svg>
这个例子中有两个动画,每个动画的分别驱动x和Ÿ的属性。
当组合<animateTransform>元素,默认的行为是第二个动画来抵消第一个。但是,您可以通过设置additive属性值为sum的而使两种动画效果累加。
<svg width="500" height="100">
<rect x="10" y="10" width="40" height="20"
style="stroke: #000000; fill: none;">
<animateTransform attributeName="transform" attributeType="XML"
type="scale"
from="1" to="3"
begin="0s" dur="10s"
repeatCount="indefinite"
additive="sum"
/>
<animateTransform attributeName="transform" attributeType="XML"
type="rotate"
from="0 30 20" to="360 30 20"
begin="0s" dur="10s"
fill="freeze"
repeatCount="indefinite"
additive="sum"
/>
</rect>
</svg>
##SVG <radialGradient> <radialGradient>元素必须嵌套在<defs>中
###示例1 径向渐变,从 white 到 blue
<svg height="150" width="500">
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
</svg>
代码说明:
###示例2
<svg height="150" width="500">
<defs>
<radialGradient id="grad2" cx="20%" cy="30%" r="30%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad2)" />
</svg>
##SVG Gradients(渐变) 渐变是指从一种颜色向另外一种颜色的平滑转换。几种颜色转化能同时作用于同一个元素中。
SVG中主要有两种渐变:
##SVG <linearGradient> <linearGradient>元素必须嵌套在<defs>中
<linearGradient>可以定义成水平、垂直、任意角度渐变:
###示例1 水平渐变,从yellow 到 red
<svg height="150" width="400">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
</defs>
<ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
</svg>
代码说明:
###示例2 垂直渐变,从yellow 到 red
<svg height="150" width="400">
<defs>
<linearGradient id="grad2" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
</defs>
<ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad2)" />
</svg>
###示例3 水平渐变,从yellow 到 red,并增加了一个文本
<svg height="150" width="400">
<defs>
<linearGradient id="grad3" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
</defs>
<ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad3)" />
<text fill="#ffffff" font-size="45" font-family="Verdana" x="150" y="86">
SVG</text>
</svg>
##SVG <feOffset>
###示例1
<svg height="120" width="120">
<defs>
<filter id="f1" x="0" y="0" width="200%" height="200%">
<feOffset result="offOut" in="SourceGraphic" dx="20" dy="20" />
<feBlend in="SourceGraphic" in2="offOut" mode="normal" />
</filter>
</defs>
<rect width="90" height="90" stroke="green" stroke-width="3"
fill="yellow" filter="url(#f1)" />
</svg>
代码解释:
###示例2 加上了 <feGaussianBlur>
<svg height="140" width="140">
<defs>
<filter id="f2" x="0" y="0" width="200%" height="200%">
<feOffset result="offOut" in="SourceGraphic" dx="20" dy="20" />
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="10" />
<feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
</defs>
<rect width="90" height="90" stroke="green" stroke-width="3"
fill="yellow" filter="url(#f2)" />
</svg>
###示例3
<svg height="140" width="140">
<defs>
<filter id="f3" x="0" y="0" width="200%" height="200%">
<feOffset result="offOut" in="SourceAlpha" dx="20" dy="20" />
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="10" />
<feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
</defs>
<rect width="90" height="90" stroke="green" stroke-width="3"
fill="yellow" filter="url(#f3)" />
</svg>
代码解释:
###示例4
<svg height="140" width="140">
<defs>
<filter id="f4" x="0" y="0" width="200%" height="200%">
<feOffset result="offOut" in="SourceGraphic" dx="20" dy="20" />
<feColorMatrix result="matrixOut" in="offOut" type="matrix"
values="0.2 0 0 0 0 0 0.2 0 0 0 0 0 0.2 0 0 0 0 0 1 0" />
<feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="10" />
<feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
</defs>
<rect width="90" height="90" stroke="green" stroke-width="3"
fill="yellow" filter="url(#f4)" />
</svg>
代码解释:
##SVG 滤镜 在 SVG 中,可用的滤镜有:
注意:
##虚化Blur Effects; <filter>标签用来定义 SVG 滤镜。<filter>标签使用必需的 id 属性来定义向图形应用哪个滤镜? <filter>标签必须嵌套在 <defs> 标签内。<defs> 标签是 definitions 的缩写,它允许对诸如滤镜等特殊元素进行定义。
###SVG <feGaussianBlur>
####示例1
<svg height="110" width="110">
<defs>
<filter id="f1" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation="15" />
</filter>
</defs>
<rect width="90" height="90" stroke="green" stroke-width="3"
fill="yellow" filter="url(#f1)" />
</svg>
代码解释:
##9.Stroke 属性 SVG stroke拥有很多属性,下面只重点讲一部分:
###stroke
stroke用来定义line、text或者元素的outline等的颜色
<svg height="80" width="300">
<g fill="none">
<path stroke="red" d="M5 20 l215 0" />
<path stroke="blue" d="M5 40 l215 0" />
<path stroke="black" d="M5 60 l215 0" />
</g>
</svg>
###stroke-width stroke-width用来定义line、text或者元素的outline等的厚度
<svg height="80" width="300">
<g fill="none" stroke="black">
<path stroke-width="2" d="M5 20 l215 0" />
<path stroke-width="4" d="M5 40 l215 0" />
<path stroke-width="6" d="M5 60 l215 0" />
</g>
</svg>
###stroke-linecap stroke-linecap定义线条结尾的不同样式
<svg height="80" width="300">
<g fill="none" stroke="black" stroke-width="16">
<path stroke-linecap="butt" d="M5 20 l215 0" />
<path stroke-linecap="round" d="M5 40 l215 0" />
<path stroke-linecap="square" d="M5 60 l215 0" />
</g>
</svg>
###stroke-dasharray stroke-dasharray定义断续线
<svg height="80" width="300">
<g fill="none" stroke="black" stroke-width="4">
<path stroke-dasharray="5,5" d="M5 20 l215 0" />
<path stroke-dasharray="10,10" d="M5 40 l215 0" />
<path stroke-dasharray="20,10,5,5,5,10" d="M5 60 l215 0" />
</g>
</svg>
###stroke-opacity stroke-opacity不透明度
<svg width="500" height="120">
<text x="22" y="40">欢迎光临www.waylau.com</text>
<path d="M20,40 l50,0"
style="stroke: #00ff00; fill:none;
stroke-width:16px;
stroke-opacity: 0.3;
" />
<path d="M80,40 l50,0"
style="stroke: #00ff00; fill:none;
stroke-width:16px;
stroke-opacity: 0.7;
" />
<path d="M140,40 l50,0"
style="stroke: #00ff00; fill:none;
stroke-width:16px;
stroke-opacity: 1;
" />
</svg>
参考:http://tutorials.jenkov.com/svg/stroke.html http://www.w3schools.com/svg/svg_stroking.asp
##8.文本 <text>
####示例8.1 写一个文本:
<svg height="30" width="200">
<text x="0" y="15" fill="red">欢迎访问wwww.waylau.com </text>
</svg>
####示例8.2 让文本转个角度:
<svg height="60" width="200">
<text x="0" y="15" fill="red" transform="rotate(10 20,40)">欢迎访问wwww.waylau.com</text>
</svg>
####示例8.3 让文本引用path:
<svg width="500" height="220">
<defs>
<path id="myTextPath2"
d="M75,20 l100,0 l100,30 q0,100 150,100"/>
</defs>
<text x="10" y="100" style="stroke: #000000;">
<textPath xlink:href="#myTextPath2">
欢迎访问www.waylau.com个人博客欢迎访问www.waylau.com
</textPath>
</text>
</svg>
####示例8.4
可以使用 <tspan> 将文本元素分成几部分,允许每部分有各自的样式
<svg height="90" width="200">
<text x="10" y="20" style="fill:red;">Several lines:
<tspan x="10" y="45">欢迎访问</tspan>
<tspan x="10" y="70">wwww.waylau.com</tspan>
</text>
</svg>
####示例8.5 使用 <a> 使文本变成一个链接
<svg height="30" width="200" xmlns:xlink="http://www.w3.org/1999/xlink">
<a xlink:href="http://www.waylau.com" target="_blank">
<text x="0" y="15" fill="red">欢迎访问wwww.waylau.com</text>
</a>
</svg>
####示例8.6 垂直样式
<svg height="260" width="200">
<text x="10" y="10" fill="red" style="writing-mode: tb; glyph-orientation-vertical: 0;">
欢迎访问wwww.waylau.com
</text>
<text x="110" y="10" fill="red" style="writing-mode: tb; glyph-orientation-vertical: 90;">
欢迎访问wwww.waylau.com
</text>
</svg>
##7.路径 <path>
下面的命令可用于路径数据:
注释:以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。
####示例7.1 例子定义了一条路径,它开始于位置 250 150,到达位置 150 350,然后从那里开始到 350 350,最后在 250 150 关闭路径。
<svg height="210" width="400">
<path d="M150 0 L75 200 L225 200 Z" />
</svg>
####示例7.2
<svg height="400" width="450">
<path id="lineAB" d="M 100 350 l 150 -300" stroke="red"
stroke-width="3" fill="none" />
<path id="lineBC" d="M 250 50 l 150 300" stroke="red"
stroke-width="3" fill="none" />
<path d="M 175 200 l 150 0" stroke="green" stroke-width="3"
fill="none" />
<path d="M 100 350 q 150 -300 300 0" stroke="blue"
stroke-width="5" fill="none" />
<!-- Mark relevant points -->
<g stroke="black" stroke-width="3" fill="black">
<circle id="pointA" cx="100" cy="350" r="3" />
<circle id="pointB" cx="250" cy="50" r="3" />
<circle id="pointC" cx="400" cy="350" r="3" />
</g>
<!-- Label the points -->
<g font-size="30" font="sans-serif" fill="black" stroke="none"
text-anchor="middle">
<text x="100" y="350" dx="-30">A</text>
<text x="250" y="50" dy="-10">B</text>
<text x="400" y="350" dx="30">C</text>
</g>
</svg>
由于绘制路径的复杂性,因此强烈建议您使用 SVG 编辑器来创建复杂的图形。推荐用开源矢量图编辑器Inkscape
##5.多边形 <polygon>
####示例5.1
<svg height="210" width="500">
<polygon points="200,10 250,190 160,210" style="fill:lime;stroke:purple;stroke-width:1" />
</svg> **代码解释:**
####示例5.2
<svg height="250" width="500">
<polygon points="220,10 300,210 170,250 123,234" style="fill:lime;stroke:purple;stroke-width:1" />
</svg>
####示例5.3
<svg height="210" width="500">
<polygon points="100,10 40,180 190,60 10,60 160,180"
style="fill:lime;stroke:purple;stroke-width:5;fill-rule:nonzero;" />
</svg>
####示例5.4 fill-rule属性改为”evenodd”
<svg height="210" width="500">
<polygon points="100,10 40,180 190,60 10,60 160,180"
style="fill:lime;stroke:purple;stroke-width:5;fill-rule:evenodd;" />
</svg>
##6.折线 <polyline>
####示例6.1
<svg height="200" width="500">
<polyline points="20,20 40,25 60,40 80,120 120,140 200,180"
style="fill:none;stroke:black;stroke-width:3" />
</svg>
####示例6.2
<svg height="180" width="500">
<polyline points="0,40 40,40 40,80 80,80 80,120 120,120 120,160"
style="fill:white;stroke:red;stroke-width:4" />
</svg>
##4.线条 <line>
####示例4.1
<svg height="210" width="500">
<line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" />
</svg> **代码解释:**
##3.椭圆 <ellipse>
####示例3.1
<svg height="140" width="500">
<ellipse cx="200" cy="80" rx="100" ry="50"
style="fill:yellow;stroke:purple;stroke-width:2" />
</svg> **代码解释:**
####示例3.2
<svg height="150" width="500">
<ellipse cx="240" cy="100" rx="220" ry="30" style="fill:purple" />
<ellipse cx="220" cy="70" rx="190" ry="20" style="fill:lime" />
<ellipse cx="210" cy="45" rx="170" ry="15" style="fill:yellow" />
</svg> ####示例3.3
<svg height="100" width="500">
<ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" />
<ellipse cx="220" cy="50" rx="190" ry="20" style="fill:white" />
</svg>