Comments (15)
兼容问题
1、字体行高 小程序在字体小于10px时,即使行高设置为1 ,字体占据位置也是10px;安卓bug
2、华为手机 华为手机删除小程序 不会删除保存的数据
3、cover-view 覆盖在原生组件之上的文本视图,可覆盖的原生组件包括map、video、canvas、camera、live-player、live-pusher,只支持嵌套cover-view、cover-image,可在cover-view中使用button。
4、打开小程序 需要真机测试
from alexuse.
wx:key
twoList:[{
"id": 1,
"name": "应季鲜果",
"count": "1",
"twodata": [{
"id": 11,
"name": "鸡脆骨"
},{
"id": 12,
"name": "鸡爪"
}]
}]
<view class="pad10" wx:for="{{twoList}}" wx:key="id">
<view>
{{index+1}}、{{item.name}}
</view>
<view wx:for="{{item.twodata}}" wx:for-item="twodata" wx:key="id">
----{{twodata.name}}---{{item.name}}
</view>
</view>
我们在wxml代码里,很明显的看到有两个wx:for的控制属性,在二层循环的JSON代码里,我们看每个单数组里还有一级数据twodata,这里是需要再循环渲染到页面上的,在第一层数据里,直接再循环item.twodata即可,请记得一定要带上花括号。
在第二层的循环里,建议把当前项的变量名改为其他,即在wxml代码里看到的wx:for-item="twodata",因为默认的当前项的变量名为item,如果不改换其他的话,你是拿不到第一层循环的数据的,因为被第二层的变量名覆盖了。
所以我们在wxml代码里,在第二层循环时,可以看到还可以循环第一层的值,即----{{twodata.name}}---{{item.name}}。
wx:key唯一标识符
为什么会有wx:key的出现呢,官方给的解释是,如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input 中的输入内容,switch 的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符。
当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
wx:key 的值以两种形式提供
1、wx:key="property" 其中property是代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。类似于字典的key值
2、wx:key="*this", 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字,如:当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
from alexuse.
target和currentTarget的区别
e.target是返回触发事件的对象 e.currentTarget返回的是绑定事件的对象。
认真看这段话:
通常情况下target和currentTarget是一致的,我们只要使用target即可,但有一种情况必须区分这两者的关系,那就是在父子嵌套的关系中,父元素绑定了事件,单击了子元素(根据事件流,在不阻止事件流的前提下他会传递至父元素,导致父元素的事件处理函数执行),这时候currentTarget指向的是父元素,因为他是绑定事件的对象,而target指向了子元素,因为他是触发事件的那个具体对象 。
在你的第一种情况中,可能触发这个事件的并非是这个子元素。所以也就没有返回你想要的那个target。
而在你的第二种情况中,可能恰巧触发这个事件的就是含有data-name的这个text标签,所以也就返回了你想看到的那个target
event.currentTarget.dataset.postid
event.target.dataset.postid
from alexuse.
button 去掉样式
.btn{
boder: none;
border-radius: none;
}
.btn::after{
boder: none;
border-radius: none;
}
from alexuse.
canvas 画图
draw 之后马上执行其他代码在真机上就是可能会出问题,需要加个 300ms 的 timeout ;
微信小程序中的 canvas 绘图组件
const canvasImg = (cObj, callback) => {
wx.showLoading({
title: '加载图片中...',
})
// canvasId, imgurl, signIn
let picPath = cObj.imgurl;
let user = cObj.usrInfo;
wx.getImageInfo({
src: cObj.imgurl,
success: function (res) {
console.log(res);
// 使用 wx.createContext 获取绘图上下文 context
var context = wx.createCanvasContext(cObj.canvasId);
var cxtW = 310;
var cxtH = 248;
var imgW = res.width;
var imgH = res.height;
//圆角半径
var r = 10;
context.save();
//安卓系统有问题
// var pattern = context.createPattern(picPath, "no-repeat");
//context.beginPath();
//context.moveTo( r, 0);
// context.arcTo(cxtW, 0, cxtW, cxtH, r);
//context.arcTo(cxtW, cxtH, 0, cxtH, r);
//context.arcTo(0, cxtH, 0, 0, r);
//context.arcTo(0, 0, cxtW, 0, r);
// context.closePath();
//context.clip();
//改用
//roundRect(r, w, h, x, y, context);
//context.clip();
//小程序目前只支持一次裁切 改用展示图片 对图片做圆角
context.drawImage(picPath, 0, 0, imgW, imgH, 0, 0, cxtW, cxtH);
context.restore();
var rpxToPxRatio = app.globalData.rpxToPxRatio;
// 是否添加签名
if (cObj.signIn) {
var avatarWidth = 68 * rpxToPxRatio; // 头像宽度
var avatarHeight = 68 * rpxToPxRatio; // 头像高度
var avatarMarginLeft = 20 * rpxToPxRatio; // 头像左间距
var avatarMarginBottom = 20 * rpxToPxRatio; // 头像底间距
var nicknameFontSize = 26 * rpxToPxRatio; // 昵称字号
var phoneNumberFontSize = 26 * rpxToPxRatio; // 号码字号
var middleFontMargin = 15 * rpxToPxRatio; // 文字中间间距
// 线性阴影
var grd = context.createLinearGradient(0, cxtH, 0, cxtH - avatarMarginBottom * 2 - avatarHeight);
grd.addColorStop(0, 'rgba(0, 0, 0, 0.8)');
grd.addColorStop(0.63, 'rgba(0, 0, 0, 0.4)');
grd.addColorStop(1, 'rgba(0, 0, 0, 0)');
context.setFillStyle(grd);
context.fillRect(0, cxtH - avatarMarginBottom * 2 - avatarHeight, cxtW, cxtH);
// 用户头像绘制
context.arc(avatarMarginLeft + avatarWidth / 2, cxtH - avatarMarginBottom - avatarHeight / 2, avatarWidth / 2, 0, Math.PI * 2, false);
context.clip();
context.drawImage(user.avatarUrl, avatarMarginLeft, cxtH - avatarMarginBottom - avatarHeight, avatarWidth, avatarHeight);
// 设置姓名样式
context.restore();
context.setFillStyle('#fefefe');
context.setFontSize(nicknameFontSize);
// 用户姓名绘制
context.fillText(user.nickName, 2 * avatarMarginLeft + avatarWidth, cxtH - avatarMarginBottom - avatarHeight + nicknameFontSize);
// 设置手机号样式
context.setFontSize(phoneNumberFontSize);
// 绘制手机号
// user.phone_number
context.fillText('1234561231', 2 * avatarMarginLeft + avatarWidth, cxtH - avatarMarginBottom - avatarHeight + nicknameFontSize + phoneNumberFontSize + middleFontMargin);
// 是否是打卡
if (cObj.clockIn) {
// 设置打卡样式
let msg = cObj.clockInMsg;
context.restore();
context.setFillStyle('#fafafa');
context.setFontSize(nicknameFontSize);
context.fillText(msg.time, 250, 210);
context.fillText("坚持打卡第" + msg.times + "天", 210, 230);
// 用户打卡信息绘制
context.setFillStyle('#aaa');
context.fillText("早起打卡 " + msg.data, 180, 20);
}
}
console.log("success");
context.draw(false, function (res) {
console.log("success");
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: cxtW,
height: cxtH,
quality: 1.0,
canvasId: cObj.canvasId,
success: function (res) {
wx.hideLoading()
var tempFilePath = res.tempFilePath
// 签名图片显示
callback(tempFilePath);
},
fail: function (res) {
console.log('canvasSigningIndex fail:', res)
},
complete: function (res) {
console.log('canvasSigningIndex complete:', res)
}
})
})
},
fail: function (res) {
console.log(res);
}
});
}
//保存canvas图片
const saveImage = (imgUrl) => {
wx.saveImageToPhotosAlbum({
filePath: imgUrl,
success(res) {
wx.showToast({
title: '图片已保存到相册',
icon: 'success',
duration: 2000
})
},
fail(res) {
wx.showToast({
title: '图片保存失败',
icon: 'none',
duration: 2000
})
}
})
}
// 绘制圆角图形
const roundRect = (r, w, h, x, y, context,cObj) =>{
// 开始绘制
// context.save();
context.beginPath();
context.setFillStyle('#ffffff');
context.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
context.moveTo(x + r, y);
context.lineTo(x + w - r, y);
context.lineTo(x + w, y + r);
context.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2);
context.lineTo(x + w, y + h - r);
context.lineTo(x + w - r, y + h);
context.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5);
context.lineTo(x + r, y + h);
context.lineTo(x, y + h - r);
context.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI);
context.lineTo(x, y + r);
context.lineTo(x + r, y);
context.closePath();
return this;
}
文字折行,打印机输出文字
参考文章:张鑫旭博客
const setQcode = (cObj, callback) => {
wx.getImageInfo({
src: cObj.extra.channelQrcodeUrl,
success: function (res) {
var rpxToPxRatio = app.globalData.rpxToPxRatio;
// 使用 wx.createContext 获取绘图上下文 context
var context = wx.createCanvasContext(cObj.canvasId);
var cxtW = 680 * rpxToPxRatio;
var cxtH = (544 + 169) * rpxToPxRatio;
context.width = cxtW;
context.height = cxtH + 500 * rpxToPxRatio;
context.save();
context.setFillStyle('#fff');
context.fillRect(0, 544 * rpxToPxRatio, 680 * rpxToPxRatio, 169 * rpxToPxRatio);
context.restore();
// 文字
context.save();
var nicknameFontSize = 26 * rpxToPxRatio; // 昵称字号
context.setFillStyle('#333');
context.setFontSize(nicknameFontSize);
// 文字折行
// cObj.imgTit
let titArr = escape2Html(cObj.imgTit).split('');
let text = ''; //循环文案
let lineHeight = 40*rpxToPxRatio;
let maxWidth = 400 * rpxToPxRatio;
let y = (544 + 70) * rpxToPxRatio;
let lineTimes = 0;
for(let n = 0;n < titArr.length;n++){
text = text + titArr[n];
let titWidth = context.measureText(text).width;
if (titWidth > maxWidth && n > 0){
context.fillText(text, 40 * rpxToPxRatio, y);
text = titArr[n];
y += lineHeight;
++lineTimes;
}else{
text;
}
if (lineTimes > 1) {
break;
}
}
if(lineTimes<2){
context.fillText(text, 40 * rpxToPxRatio, y);
}
context.restore();
// 图片title
// context.fillText(cObj.imgTit, 40 * rpxToPxRatio, (544 + 60) * rpxToPxRatio,400*rpxToPxRatio);
// 二维码
context.save();
context.beginPath();
context.drawImage(res.path, (680 - 129 - 20) * rpxToPxRatio, (544 +169 - 20 - 129) * rpxToPxRatio, 129 * rpxToPxRatio, 129 * rpxToPxRatio);
context.restore();
context.draw(true, function (res) {
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: cxtW,
height: cxtH,
quality: 1.0,
canvasId: cObj.canvasId,
success: function (temp) {
wx.hideLoading();
var tempFilePath = temp.tempFilePath;
// 签名图片显示
callback(tempFilePath);
// console.log('canvasSigningIndex success:', tempFilePath)
},
fail: function (tempFile) {
wx.showToast({
title: '获取二维码失败,请稍后重试',
icon: 'none'
})
},
complete: function (tempCom) {
// console.log('canvasSigningIndex complete:', tempCom)
}
})
})
}
});
}
from alexuse.
canvas 字体阴影
context.save();
context.beginPath();
context.setFontSize(phoneNumberFontSize);//字体大小
context.setLineWidth(4);//线条宽度
context.setShadow(2,2,2,'#000');//设置阴影
context.setStrokeStyle('#33ff66');//线条样式
context.setFillStyle('#fff');
context.fillText("早起打卡 " + msg.date, 400 * rpxToPxRatio, 48 * rpxToPxRatio);
context.closePath();
context.stroke();
from alexuse.
canvas.save() canvas.restore() 作用
canvas.save();和canvas.restore();是两个相互匹配出现的,作用是用来保存画布的状态和取出保存的状态的。保存绘制状态和防止污染状态栈。
save()保存的只是CanvasRenderingContext2D对象的状态以及对象的所有属性,并不包括这个对象上绘制的图形。
当我们对画布进行旋转,缩放,平移等操作的时候其实我们是想对特定的元素进行操作,比如图片,一个矩形等,但是当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作,那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态,当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响
在Canvas环境中绘图时,可以利用所谓的绘图堆栈状态。每个状态随时存储Canvas上下文数据。下面是存储在状态堆栈的数据列表。
- 当前的坐标变换(变换矩阵)信息,比如旋转或平移时使用的rotate()和setTransform()方法
- 当前剪贴区域
- 图形上下文对象(CanvasRenderingContext2D)的当前属性值
CanvasRenderingContext2D的当前属性值主要包括:
- canvas 取得画布元素
- fillStyle 填充路径的当前的颜色、模式或渐变
- globalCompositeOperation 指定颜色如何与画布上已有颜色组合(合成)
- lineCap 指定线段端点的绘制方式
- lineJoin 指定线段连接的绘制方式
- lineWidth 绘制线段的宽度
- miterLimit 当lineJoin为miter时,这个属性指定斜连接长度和二分之一线宽的最大比率
- shadowBlur 指定阴影模糊度
- shadowColor 指定阴影颜色
- shadowOffsetX 指定阴影水平偏移值
- shadowOffsetY 指定阴影垂直偏移值
- strokeStyle 指定线段颜色
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
原文: https://www.w3cplus.com/canvas/canvas-states.html © w3cplus.com
from alexuse.
小程序更新
if (wx.getUpdateManager){
const updateManager = wx.getUpdateManager(); //管理小程序更新
updateManager.onCheckForUpdate(function (res) {
// 请求完新版本信息的回调
// console.log(res.hasUpdate)
})
updateManager.onUpdateReady(function () {
wx.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success: function (res) {
if (res.confirm) {
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate()
}
}
})
})
updateManager.onUpdateFailed(function () {
// 新的版本下载失败
})
}
from alexuse.
封装wx.request来判断是否断网
1、封装wx.request来判断是否断网,及断网后记录本次请求;
2、当网络断开时,你可以给用户一个提示,告诉用户网络连接有问题,重新连接之后,让用户自己去点击加载的按钮,也就相当于重新加载了
function wxRequest (obj, cb, page, type) {
var isOne = true
var cachFn = function () {
wx.request({
url: obj.url,
data: obj.data || {},
method: obj.method || 'GET',
success: function (res) {
cb.call(page, res)
if (!page.data.isNet) {
page.setData({
isNet: true
})
}
},
// fail执行时当断网处理
fail: function () {
// 防止fail 有时会执行两次,影响渲染
if (!isOne) {
return
}
page.setData({
isNet: false,
isRequested: false
})
// 记录本次请求,加载时,执行page实例的reloadFn即可
page.reloadFn = wxRequest(obj, cb, page, 1)
isOne = false
}
})
}
if (type) {
page.isRequested = true
}
return type ? cachFn : cachFn()
}
let data = {
url: '',
data: {},
method: ''
}
wxTools.wxRequest(data, (res) => {
// 数据渲染
this.setData({})
}, this)
from alexuse.
什么是优秀的小程序?
1、首屏加载时间 2s
下载小程序代码包 --> 打开应用 1M 以内 平均小于1.5s
- 去除冗余代码、多余图片等资源
- 非必要的图片资源放在云端
- 压缩图片体积
- 分包技术(1、核心功能--主包 2、功能 -- 分包审核)
2、渲染
渲染单页时间不超过值 IOS -- 200ms Android -- 500ms
- 快速呈现页面数据 数据存储在本地 下次打开时读取本地数据
- 减少单次拉取数据量 分页
- 需要用户等待时给予适当提示
3、交互
- 减少用户输入 授权获取微信手机号 不活跃直接发送验证码;静默登录 京东购物流程没有打断直接付款购物即可(绑定到原有账户)
扫一扫 | 蓝牙 | 收货地址 |
---|---|---|
到店订餐 | 会议签到 | 电商购物 |
扫描商品 | 到店领取优惠 | 寄送快递 |
开启共享单车 | 手机开门 | 寄送回执 |
公司打卡 |
- 需要授权时再弹窗 流失率 30%以上 用户取消授权:提供手动输入能力 or 引导用户再次开启
- 用户操作及时反馈 点击反馈
启动快、感受快、操作快
from alexuse.
getPhoneNumber(OBJECT)
1、需先调用login接口
2、需要用户主动触发才能发起获取手机号接口,需用 组件的点击来触发
3、目前该接口针对非个人开发者,且完成了认证的小程序开放。
4、使用方法:将 组件 open-type 的值设置为 getPhoneNumber,当用户点击并同意之后,可以通过 bindgetphonenumber 事件回调获取到微信服务器返回的加密数据, 然后在第三方服务端结合 session_key 以及 app_id 进行解密获取手机号。
5、在回调中调用 wx.login 登录,可能会刷新登录态。此时服务器使用 code 换取的 sessionKey 不是加密时使用的 sessionKey,导致解密失败。建议开发者提前进行 login;或者在回调中先使用 checkSession 进行登录态检查,避免 login 刷新登录态。
from alexuse.
倒计时
60秒倒计时
// 声明函数 common.js
const countDown = (that) =>{
let countDownNum =that.data.countDown
console.log(countDownNum)
if (countDownNum == 0) {
that.setData({
requestCode: false
});
return;
}
let timer = setTimeout(function(){
--countDownNum;
that.setData({
countDown: countDownNum
});
countDown(that);
}, 100);
}
const clearTimeout = (timer) => {
clearTimeout(timer);
}
//引用函数页
changeTime: function(){
let that = this;
clearTimeout();
util.countDown(that);
}
from alexuse.
mpvue
//子组件
<template></template>
export default {
props:{},
data():{},
methods:{
getVerifyCode(){
thiz.$parent.getVerifyCode(phoneNumber,interval);
}
}
}
<verify :showPop="isShow" :inputVal="phoneNumber" :parent-cancel="cancel" @parent-binding="binding(msg)"
@parent-msg="showToast(msg)"></verify>
//父组件
import Verify from "@/components/verify-phone";
getVerifyCode(phoneNumber,interval){
clearInterval(interval)
}
Flyio简介
要上述问题,就需要一个能支持多个平台网络库,用户层提供统一的API,将平台差异在底层屏蔽。而 Fly.js就是这酱紫的一个网络库,为了方便axios使用者迁移,fly.js API设计风格和axios相似(但不完全相同)!
Fly.js 通过在不同 JavaScript 运行时通过在底层切换不同的 Http Engine来实现多环境支持,但同时对用户层提供统一、标准的Promise [API。不仅如此,Fly.js还支持请求/响应拦截器、自动转化JSON、请求转发等功能,详情请参考:https://github.com/wendux/fly 。
var Fly=require("flyio/dist/npm/wx")
var fly=new Fly
... //添加全局配置、拦截器等
Vue.prototype.$http=fly //将fly实例挂在vue原型上
//组件中使用
this.$http.get("/test",{xx:6}).then((d)=>{
//输出请求数据
console.log(d.data)
//输出响应头
console.log(d.header)
}).catch(err=>{
console.log(err.status,err.message)
})
vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
什么是“状态管理模式”?
new Vue({
// state
data () {
return {
count: 0
}
},
// view
template: `
<div>{{ count }}</div>
`,
// actions
methods: {
increment () {
this.count++
}
}
})
这个状态自管理应用包含以下几个部分:
-
state,驱动应用的数据源;
-
view,以声明方式将 state 映射到视图;
-
actions,响应在 view 上的用户输入导致的状态变化。
但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏: -
多个视图依赖于同一状态。
-
来自不同视图的行为需要变更同一状态。
对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护。
这就是 Vuex 背后的基本**,借鉴了 Flux、Redux、和 The Elm Architecture。与其他模式不同的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。
- components 组件
- dispatch 发送
- commit 保证,承诺
- mutations 变动
- devtools 开发工具
- mutate 变异
- render 呈送
什么情况下我应该使用 Vuex?
虽然 Vuex 可以帮助我们管理共享状态,但也附带了更多的概念和框架。
from alexuse.
emoji 问题
更新用户昵称及头像,大概1~2 个小时 open-type="getUserInfo" 可以拿到最新数据
从 wx.getUserInfo 拿到的 nickName 里的 emoji 采用的是 Softbank 编码,而浏览器和小程序支持的是 Unified,我的小程序是自己做了编码转换。
http://www.oicqzone.com/tool/emoji/
from alexuse.
小程序 生成二维码
微信小程序中生成二维码工具:weapp.qrcode.js
通过js生成了二维码,那就是到 =>转成图片生成临时文件路径=>previewImage预览图片=>长按转发, 这个是不是相当于只转发了一张图片
from alexuse.
Related Issues (20)
- js高级(第三版) HOT 4
- css 样式问题 HOT 7
- js HOT 23
- CSS HOT 4
- TCP/IP HOT 1
- Web高效编程与优化
- serializeArr 转为 serializeJson
- 关于重构 HOT 1
- 从浏览器输入网址到页面展示完成发生了什么
- Echarts HOT 1
- layui 使用遇到的问题 HOT 3
- 多文件上传 jquery.MultiFile
- 常用正则 HOT 1
- 隐藏 表单记录 多选框选中
- node 相关
- js 判断浏览器类型以及语言
- GIT HOT 2
- 工具使用
- 设计模式
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from alexuse.