原文:C# WPF 低仿网易云音乐(PC)Banner动画控件

由于技术有限没能做到一模一样的动画,只是粗略地做了一下。动画有点生硬,还有就是没做出网易云音乐的立体感。代码非常简单粗暴,而且我也写有很多注释,这里就不多啰嗦了,直接贴代码。

算了,啰嗦几句。原理是这样的,在自定义用户控件内添加3个border(左、中、右,以下分别简称为:b1、b2、b3),对border进行缩放和移动动画。往右切换时b1放大平移到b2的位置,b2缩小平移到b3的位置,b3平移到b1的位置,动画结束后重新记录3个border的左、中、右位置,然后如此循环。一次滚动有三个动画,分别写了3个方法来定义。

可加上透明动画、阴影,应该会更加好看些。

没有实现调用的方法,只是个纯动画项目,图片也是写死在前台代码中,需要在项目中使用时自行简单地修改即可。

低仿效果

网易云音乐原版

代码

后台

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading; namespace 网易云音乐Banner动画.Controls
{
/// <summary>
/// CloudMusicBanner.xaml 的交互逻辑
/// </summary>
public partial class CloudMusicBanner : UserControl
{ //代码所用涉及时间单位均是:秒
#region 一些变量
//左、中、右三张banner的位置
double leftlocation = , centerlocation = , rightlocation = ;
//每张banner的动画执行时间
double AnimationTime = 0.4;
//非中间banner的遮盖层透明度
double bopacity = 0.65;
//没有交互时动画自动执行间隔时间
double timeranimation_time = ;
//动画播放状态(当前动画是否在执行)
bool isplay = false;
//三个banner border变量,用于暂时保存
Border b_left, b_center, b_right;
//通用缓动函数,提升动画流畅感
EasingFunctionBase easeFunction;
//banner集合,用于定位和记录border的位置(左,中,右)
Dictionary<Location, Border> Banners = new Dictionary<Location, Border>();
DispatcherTimer timeranimation;
#endregion public CloudMusicBanner()
{
InitializeComponent(); //将三张banner(border)添加到banner集合
Banners.Add(Location.Left, left);
Banners.Add(Location.Center, center);
Banners.Add(Location.Right, right); //控件加载完成后
Loaded += (e, c) =>
{
//首次启动设置三张banner的位置、大小信息
SetLocation(Location.Left, left);
SetLocation(Location.Center, center);
SetLocation(Location.Right, right); //启动定时器,用于自动播放滚动动画
TimerAnimationStart();
}; //初始化缓动函数
//quadraticease的easeout mode是从快到慢
//参考了博客:http://www.cnblogs.com/xwlyun/archive/2012/09/11/2680579.html
easeFunction = new QuadraticEase()
{
EasingMode = EasingMode.EaseOut
}; //初始化定时器
timeranimation = new DispatcherTimer();
//设置定时器的间隔时间
timeranimation.Interval = TimeSpan.FromSeconds(timeranimation_time); } #region 交互事件 private void UserControl_MouseEnter(object sender, MouseEventArgs e)
{
//鼠标移入控件时显示两个“左/右”图标按钮
toleftbtn.Opacity = ;
} private void UserControl_MouseLeave(object sender, MouseEventArgs e)
{
//鼠标移出控件时隐藏两个“左/右”图标按钮 toleftbtn.Opacity = ;
} private void toleftbtn_Click(object sender, RoutedEventArgs e)
{
//向左图标按钮点击
LeftAnimation();
} private void torightbtn_Click(object sender, RoutedEventArgs e)
{
RightAnimation();
}
#endregion //左切换动画时三张banner向右滚动
/*
* 即中间的border移动至:右
* 右边的border移动至:左
* 左边的border移动至:中
*/
#region 左切换动画
public void LeftAnimation()
{
//启动动画时停止定时器
timeranimation.Stop();
//设置动画播放状态为真
isplay = true; //启动相应的动画
LefttoCenterAnimation(); CentertoRightAnimation(); RighttoLeftAnimation(); }
//【仅注释此方法,以下代码均大多重复故不再注释】
#region 左切换动画-中向右动画
public void CentertoRightAnimation()
{
//记录动画结束后的位置,即当动画结束后中间的BORDER移动到右变成了右,代码:Banners[Location.Right] = b_center;
b_center = Banners[Location.Center]; //设置一下border的显示层级
Grid.SetZIndex(Banners[Location.Center], ); //获取透明遮盖图层,设置透明度
/*
* <Grid Background="Black" Panel.ZIndex="2"></Grid>
* 透明遮盖图层在设计代码中的每个border内
*
*/
GetOpacityGrid(b_center).Opacity = bopacity; //定义一个缩放转换对象(用于banner从大到小的动画)
ScaleTransform scale = new ScaleTransform();
//需要设置中心点y坐标为控件的高度,不设置的话border是靠在顶部执行动画的。
scale.CenterY = this.ActualHeight; //定义一个水平移动转换对象
TranslateTransform ts = new TranslateTransform(); //定义一个转换集合
TransformGroup group = new TransformGroup();
//将上面的缩放、平移转换对象添加到集合
group.Children.Add(scale);
group.Children.Add(ts); //将转换集合赋予给中心banner
Banners[Location.Center].RenderTransform = group; //定义一个缩放动画
DoubleAnimation scaleAnimation = new DoubleAnimation()
{
//从1(100%即默认比例)
From = ,
//到0.95(95%即从默认比例缩小到95%的比例大小)
To = 0.95,
//设置缓动函数
EasingFunction = easeFunction,
//动画执行所需时间
Duration = TimeSpan.FromSeconds(AnimationTime) }; //定义一个移动动画(用于banner从左到右.....移动动画等)
DoubleAnimation moveAnimation = new DoubleAnimation()
{
//从中心banner位置
From = centerlocation,
//移动到右banner位置
To = rightlocation,
EasingFunction = easeFunction,
Duration = TimeSpan.FromSeconds(AnimationTime) };
//启动缩放动画
scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation); //启动平移动画
ts.BeginAnimation(TranslateTransform.XProperty, moveAnimation); } #endregion
#region 左切换动画-右向左动画
public void RighttoLeftAnimation()
{
b_right = Banners[Location.Right]; Grid.SetZIndex(Banners[Location.Right], );
GetOpacityGrid(b_right).Opacity = bopacity; ScaleTransform scale = new ScaleTransform(); //缩放
scale.CenterY = this.ActualHeight;
TranslateTransform ts = new TranslateTransform();//平移 TransformGroup group = new TransformGroup();
group.Children.Add(scale);
group.Children.Add(ts); Banners[Location.Right].RenderTransform = group; DoubleAnimation scaleAnimation = new DoubleAnimation()
{
From = 0.85,
To = 0.95,
EasingFunction = easeFunction,
Duration = TimeSpan.FromSeconds(AnimationTime) }; DoubleAnimation moveAnimation = new DoubleAnimation()
{ From = rightlocation,
To = leftlocation,
EasingFunction = easeFunction,
Duration = TimeSpan.FromSeconds(AnimationTime) }; //scaleAnimation.Completed += new EventHandler(scaleAnimation_Completed);
// AnimationClock clock = scaleAnimation.CreateClock();
scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation); //启动平移动画
ts.BeginAnimation(TranslateTransform.XProperty, moveAnimation); } #endregion
#region 左切换动画-左向中动画
public void LefttoCenterAnimation()
{
b_left = Banners[Location.Left]; Grid.SetZIndex(Banners[Location.Left], ); GetOpacityGrid(b_left).Opacity = ; ScaleTransform scale = new ScaleTransform(); //缩放 //scale.CenterX = 0;
scale.CenterY = this.ActualHeight;
TranslateTransform ts = new TranslateTransform();//平移 TransformGroup group = new TransformGroup();
group.Children.Add(scale);
group.Children.Add(ts); Banners[Location.Left].RenderTransform = group; DoubleAnimation scaleAnimation = new DoubleAnimation()
{ From = 0.95,
To = ,
EasingFunction = easeFunction,
Duration = TimeSpan.FromSeconds(AnimationTime) }; DoubleAnimation moveAnimation = new DoubleAnimation()
{ From = leftlocation,
To = centerlocation,
EasingFunction = easeFunction,
Duration = TimeSpan.FromSeconds(AnimationTime) }; scaleAnimation.Completed += new EventHandler(LeftAnimation_Completed);
// AnimationClock clock = scaleAnimation.CreateClock();
scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation); //启动平移动画
ts.BeginAnimation(TranslateTransform.XProperty, moveAnimation); } #endregion #region 动画结束
private void LeftAnimation_Completed(object sender, EventArgs e)
{
//动画结束后将banner集合的位置重新设置
Banners[Location.Left] = b_right;
Banners[Location.Center] = b_left;
Banners[Location.Right] = b_center;
//此时动画结束
isplay = false;
//启动定时器
TimerAnimationStart();
}
#endregion
#endregion #region 右切换动画
public void RightAnimation()
{
timeranimation.Stop(); isplay = true; LefttoRightAnimation(); CentertoLeftAnimation(); RighttoCenterAnimation(); } #region 右切换动画-左向右动画
public void LefttoRightAnimation()
{
b_left = Banners[Location.Left];
Grid.SetZIndex(Banners[Location.Left], );
GetOpacityGrid(b_left).Opacity = bopacity;
ScaleTransform scale = new ScaleTransform(); //缩放
scale.CenterY = this.ActualHeight; TranslateTransform ts = new TranslateTransform();//平移 TransformGroup group = new TransformGroup();
group.Children.Add(scale); group.Children.Add(ts); Banners[Location.Left].RenderTransform = group; DoubleAnimation scaleAnimation = new DoubleAnimation()
{
From = 0.85,
To = 0.95,
EasingFunction = easeFunction,
Duration = TimeSpan.FromSeconds(AnimationTime) };
DoubleAnimation moveAnimation = new DoubleAnimation()
{ From = leftlocation,
To = rightlocation,
EasingFunction = easeFunction,
Duration = TimeSpan.FromSeconds(AnimationTime) }; scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation); //启动平移动画
ts.BeginAnimation(TranslateTransform.XProperty, moveAnimation); } #endregion
#region 右切换动画-中向左动画
public void CentertoLeftAnimation()
{
b_center = Banners[Location.Center]; Grid.SetZIndex(Banners[Location.Center], );
GetOpacityGrid(b_center).Opacity = bopacity; ScaleTransform scale = new ScaleTransform(); //缩放
scale.CenterY = this.ActualHeight;
TranslateTransform ts = new TranslateTransform();//平移 TransformGroup group = new TransformGroup();
group.Children.Add(scale);
group.Children.Add(ts); Banners[Location.Center].RenderTransform = group; DoubleAnimation scaleAnimation = new DoubleAnimation()
{
From = ,
To = 0.95,
EasingFunction = easeFunction,
Duration = TimeSpan.FromSeconds(AnimationTime) }; DoubleAnimation moveAnimation = new DoubleAnimation()
{ From = centerlocation,
To = leftlocation,
EasingFunction = easeFunction,
Duration = TimeSpan.FromSeconds(AnimationTime) }; //scaleAnimation.Completed += new EventHandler(scaleAnimation_Completed);
// AnimationClock clock = scaleAnimation.CreateClock();
scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation); //启动平移动画
ts.BeginAnimation(TranslateTransform.XProperty, moveAnimation); } #endregion
#region 右切换动画-右向中动画
public void RighttoCenterAnimation()
{
b_right = Banners[Location.Right];
//SetZindex(b_right);
Grid.SetZIndex(Banners[Location.Right], ); GetOpacityGrid(b_right).Opacity = ; ScaleTransform scale = new ScaleTransform(); //缩放 //scale.CenterX = 0;
scale.CenterY = this.ActualHeight;
TranslateTransform ts = new TranslateTransform();//平移 TransformGroup group = new TransformGroup();
group.Children.Add(scale);
group.Children.Add(ts); Banners[Location.Right].RenderTransform = group; DoubleAnimation scaleAnimation = new DoubleAnimation()
{
To = ,
From = 0.95,
EasingFunction = easeFunction,
Duration = TimeSpan.FromSeconds(AnimationTime) }; DoubleAnimation moveAnimation = new DoubleAnimation()
{ From = rightlocation,
To = centerlocation,
EasingFunction = easeFunction,
Duration = TimeSpan.FromSeconds(AnimationTime) }; scaleAnimation.Completed += new EventHandler(RightAnimation_Completed);
// AnimationClock clock = scaleAnimation.CreateClock();
scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation); //启动平移动画
ts.BeginAnimation(TranslateTransform.XProperty, moveAnimation); } #endregion
#region 动画结束
private void RightAnimation_Completed(object sender, EventArgs e)
{
Banners[Location.Left] = b_center;
Banners[Location.Center] = b_right;
Banners[Location.Right] = b_left;
isplay = false;
TimerAnimationStart();
}
#endregion
#endregion #region 初始化设置控件位置
//定义一个枚举类用于标识左中右三个banner(border),方便操作时获取到。
public enum Location
{
Left, Center, Right
}
//设置三个border的大小和位置
public void SetLocation(Location l, Border g)
{ //banner的大小
g.Width = ;
g.Height = ; //给除中间banner外的border缩小一些
ScaleTransform scaleTransform = new ScaleTransform();
scaleTransform.ScaleX = 0.95;
scaleTransform.ScaleY = 0.95;
scaleTransform.CenterY = this.ActualHeight;
//获取设置遮盖层的透明度
Grid opacity_grid = GetOpacityGrid(g);
opacity_grid.Opacity = bopacity;
switch (l)
{
case Location.Left: TranslateTransform tt_left = new TranslateTransform()
{
X =
};
TransformGroup group_left = new TransformGroup();
group_left.Children.Add(tt_left);
group_left.Children.Add(scaleTransform);
g.RenderTransform = group_left; break;
case Location.Center:
opacity_grid.Opacity = ; TransformGroup group_center = new TransformGroup(); //计算中心banner的x位置
centerlocation = (this.ActualWidth - g.ActualWidth) / ;
TranslateTransform tt_center = new TranslateTransform()
{
X = centerlocation
};
group_center.Children.Add(tt_center);
g.RenderTransform = group_center;
Grid.SetZIndex(g, );
break;
case Location.Right:
//Grid.SetZIndex(g, 3); //计算右banner的X位置
rightlocation = (this.ActualWidth - Banners[Location.Left].ActualWidth * 0.95); TranslateTransform tt_right = new TranslateTransform()
{
X = rightlocation
};
TransformGroup group_right = new TransformGroup();
//这里要注意先后顺序,否则位置会有偏差,必须先缩放再设置X坐标。
group_right.Children.Add(scaleTransform);
group_right.Children.Add(tt_right);
g.RenderTransform = group_right; break;
} }
#endregion //获取透明覆盖层
//代码来自:https://www.cnblogs.com/udoless/p/3381411.html
#region 获取透明覆盖层
public Grid GetOpacityGrid(DependencyObject g)
{
Grid opacity_grid = GetChild<Grid>(g, typeof(Grid));
opacity_grid = GetChild<Grid>(opacity_grid, typeof(Grid));
return opacity_grid;
}
public T GetChild<T>(DependencyObject obj, Type typename) where T : FrameworkElement
{
DependencyObject child = null;
List<T> childList = new List<T>(); for (int i = ; i <= VisualTreeHelper.GetChildrenCount(obj) - ; i++)
{
child = VisualTreeHelper.GetChild(obj, i); if (child is T && (((T)child).GetType() == typename))
{
return ((T)child);
} }
return null;
}
#endregion #region 定时唤醒动画
public void TimerAnimationStart()
{
if (timeranimation.IsEnabled == false)
{ timeranimation.Start();
}
timeranimation.Tick += (e, c) =>
{ timeranimation.Stop();
if (isplay == false)
{
RightAnimation();
}
};
}
#endregion
}
}

前台

<UserControl x:Class="网易云音乐Banner动画.Controls.CloudMusicBanner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" d:DesignHeight="200" d:DesignWidth="762" MouseEnter="UserControl_MouseEnter" MouseLeave="UserControl_MouseLeave" >
<Grid>
<!--两个图标按钮,鼠标进入时显示-->
<Button Name="toleftbtn" Opacity="0" Click="toleftbtn_Click" BorderThickness="0" HorizontalAlignment="Left" Background="Transparent" Panel.ZIndex="99" Width="50" Height="50" Cursor="Hand">
<Image Source="/网易云音乐Banner动画;component/Res/左.png" Width="16" Height="16"></Image>
</Button>
<Button Name="torightbtn" Opacity="{Binding ElementName=toleftbtn,Path=Opacity}" Click="torightbtn_Click" BorderThickness="0" HorizontalAlignment="Right" Background="Transparent" Panel.ZIndex="99" Width="50" Height="50" Cursor="Hand">
<Image Source="/网易云音乐Banner动画;component/Res/右.png" Width="16" Height="16"></Image>
</Button> <Grid HorizontalAlignment="Left"> <!--左边的banner-->
<Border BorderBrush="#000000" BorderThickness="0" Width="540" Name="left" Background="Black">
<Grid>
<!--透明遮盖层-->
<Grid Background="Black" Panel.ZIndex="2"></Grid>
<!--banner图片-->
<Image Source="/网易云音乐Banner动画;component/Res/banner1.jpg" Stretch="Fill"></Image>
</Grid>
</Border> <!--中间的banner-->
<Border BorderBrush="#96b0b3" BorderThickness="0" Width="540" Name="center" Background="Yellow" >
<Grid>
<Grid Background="Black" Panel.ZIndex="2"></Grid>
<Image Source="/网易云音乐Banner动画;component/Res/banner2.jpg" Stretch="Fill"></Image>
</Grid>
</Border> <!--右边的banner-->
<Border BorderBrush="#ab1491" BorderThickness="1" Name="right" Background="Red">
<Grid>
<Grid Background="Black" Panel.ZIndex="2"></Grid>
<Image Source="/网易云音乐Banner动画;component/Res/banner3.jpg" Stretch="Fill"></Image>
</Grid> </Border> </Grid>
</Grid>
</UserControl>

被你发现了

项目下载在这

点我下载项目源码

C# WPF 低仿网易云音乐(PC)Banner动画控件的更多相关文章

  1. C# WPF 低仿网易云音乐(PC)歌词控件

    原文:C# WPF 低仿网易云音乐(PC)歌词控件 提醒:本篇博客记录了修改的过程,废话比较多,需要项目源码和看演示效果的直接拉到文章最底部~ 网易云音乐获取歌词的api地址 http://music ...

  2. 网易云音乐PC端刷曲快捷键

    文章首发于szhshp的第三边境研究所(szhshp.org), 转载请注明 网易云音乐PC端刷曲快捷键   好吧我承认我特别懒 云音乐其实做的还不错,FM推荐的算法明显比虾米好. 虾米可以听的曲子都 ...

  3. 《云阅》一个仿网易云音乐UI,使用Gank.Io及豆瓣Api开发的开源项目

    CloudReader 一款基于网易云音乐UI,使用GankIo及豆瓣api开发的符合Google Material Desgin阅读类的开源项目.项目采取的是Retrofit + RxJava + ...

  4. 网易云音乐PC客户端加密API逆向解析

    1.前言 网上已经有大量的web端接口解析的方法了,但是对客户端的接口解析基本上找不到什么资料,本文主要分析网易云音乐PC客户端的API接口交互方式. 通过内部的代理设置,使用fiddler作为代理工 ...

  5. Flutter仿网易云音乐:播放界面

    写在前头 本来是要做一个仿网易云音乐的flutter项目,但是因为最近事情比较多,项目周期跨度会比较长,因此分几个步骤来完成.这是仿网易云音乐项目系列文章的第一篇.没有完全照搬网易云音乐的UI,借鉴了 ...

  6. 新鲜出炉高仿网易云音乐 APP

    我的引语 晚上好,我是吴小龙同学,我的公众号「一分钟GitHub」会推荐 GitHub 上好玩的项目,一分钟 get 一个优秀的开源项目,挖掘开源的价值,欢迎关注我. 项目中成长是最快的,如何成长,就 ...

  7. C# WPF 仿网易云音乐(PC)Banner动画控件

    在自定义用户控件内添加3个border(左.中.右,以下分别简称为:b1.b2.b3),对border进行缩放和移动动画.往右切换时b1放大平移到b2的位置,b2缩小平移到b3的位置,b3平移到b1的 ...

  8. WPF仿网易云音乐系列(一、左侧菜单栏:Expander+RadioButton)

    1.简介 上一篇咱们说到,网易云音乐的左侧菜单栏可以通过Expander+RadioButton来实现,具体如何实现,咱们下面开始干: 首先来一张网易云音乐PC版原图(个人觉得PC版比UWP版左侧菜单 ...

  9. WPF仿网易云音乐系列(序)

    1.简介 由于之前做了一个播放器,苦于不懂界面设计,只得去借鉴借鉴一些成功的作品,网易云音乐就甚合朕心,哈哈,最后做出来的效果如下: 本系列文章就来和大家讨论以下,如何用WPF去仿制一个网易云音乐来: ...

随机推荐

  1. SQL基础总结——20150730

           SQL SQL 指结构化查询语言 SQL 使我们有能力訪问数据库 SQL 是一种 ANSI(美国国家标准化组织) 的标准计算机语言 SQL 是一门 ANSI 的标准计算机语言.用来訪问和 ...

  2. 特殊类型数据:IP地址字段(IPv4)

    人们经常使用varchar(15)来存储ip地址,然而,它们实际上是32位无符号整数,不是字符串. MySQL提供INET_ATON()和INET_NTOA()函数将ip地址在整数和四段表示形式之间进 ...

  3. stm32的DMA重新工作

    下面是在战舰V3寄存器程序例子中找到的: //开启一次DMA传输void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx){    DMA_CHx->CCR&a ...

  4. mysql 查询字段名所在的表

    select * from (select * from information_schema.COLUMNS where table_schema = '数据库名') temp where colu ...

  5. 洛谷 P4013 数字梯形问题

    ->题目链接 题解: 网络流. #include<cstdio> #include<iostream> #include<queue> #include< ...

  6. php array数组的相关处理函数and str字符串处理与正则表达式

    下面给各位同学整理了一些关于php array数组的相关处理函数and str字符串处理与正则表达式,希望文章对你会有所帮助.   数组的相关处理函数: 1)数组的键值操作函数 array_value ...

  7. php计算两个坐标直线距离

    function rad($d) { return $d * 3.1415926535898 / 180.0; } function GetDistance($lat1, $lng1, $lat2, ...

  8. IE浏览器下css hack

    \9    :所有IE浏览器都支持 _和-  :仅IE6支持 *     :IE6.IE7支持 \0    :IE8.IE9支持 \9\0  :IE8部分支持.IE9支持 \0\9  :IE8.IE9 ...

  9. php课程 4-14 数组如何定义使用

    php课程 4-14  数组如何定义使用 一.总结 1.各种语言键值对取值和赋值赋值表达式左边的特点是什么? 键值对,用于取值和赋值,取值和赋值的左边都是一样的 2.各种语言键值对取值或者赋值的时候如 ...

  10. ZBar 是款桌面电脑用条形码/二维码扫描工具

    ZBar 是款桌面电脑用条形码/二维码扫描工具 windows平台python 2.7环境编译安装zbar   最近一个项目需要识别二维码,找来找去找到了zbar和zxing,中间越过无数坑,总算基本 ...