maxep / mxparallaxheader Goto Github PK
View Code? Open in Web Editor NEWSimple parallax header for UIScrollView
License: MIT License
Simple parallax header for UIScrollView
License: MIT License
I'm using the parallax header as a header for a collection view, the idea is to have a header, collapsable to certain point, with a search field and other stuff. The thing is when the user click or the search field becomes first responder, the content offset of the header seems to be changed and makes the collection view scrolls down. I'm not sure if is a problem of the library, but just wanted to let you know. I'm going to get it working by myself.
In my tableview, there's a setting where user can toggle to disable the parallaxHeader. Is there a property for that?
Currently, I'm doing
tableView.parallaxHeader.view = nil
tableView.parallaxHeader.height = 0
tableView.parallaxHeader.minimumHeight = 0
This hide the parallaxHeader, but when I pull the tableView and it bounce, I'm still seeing UIImageView I set before. This feels wrong.
tableView.parallaxHeader.view = imageView
I have added a UITableView as a subview of MXScrollView and encountered the issue that the Pan gesture of MXScrollView conflicts with UITableview didSelect gesture
This happens if I scroll the view partially and try to tap on a UITableViewCell, the tap is not detected for the first time, it works for the second tap.
[(MXScrollView*)scrollView scrollViewDidScroll:scrollView];
if ([self.delegate respondsToSelector:_cmd]) {
[self.delegate scrollViewDidScroll:scrollView];
}
i have a table view inside every row one one collection view present and horizontal can scroll every time scroll the parallaxHeader also effecting because of this i facing problem . how i will solve this problem help me???? @maxep
thanks
Thank you for making this plugin. It's awesome.
I have a table view with a transparant navigation and statusbar and I want the top of the parallax view to be at x = 0 (top of statusbar).
Previously when I just had a plain table header view, this worked OK. Now with MXParallaxHeader it's a bit different. Somehow I can't achieve the same behavior. See screenshot as to where it stops. The blue part is the top of the table view header. You can see the back arrow of the navigation bar halfway. There is whitespace between the parallax view top and the status bar area.
I do note that by scrolling and flicking I sometimes can actually get the parallax in the right position!
Here's a bit of my code:
self.navigationController.navigationBar.translucent = YES;
// make status bar + navbar translucent so it can show table header background image
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage = [UIImage new];
self.navigationController.toolbarHidden = FALSE;
[self.navigationController.navigationBar setBackgroundColor:[UIColor clearColor]];
// place table header view under statusbar by offsetting the table view
CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
self.tableView.contentInset = UIEdgeInsetsMake(statusBarHeight, 0, 0, 0);
// Parallax Header
self.tableView.parallaxHeader.view = self.flightDetailHeadView;
self.tableView.parallaxHeader.height = 280.0f;
self.tableView.parallaxHeader.mode = MXParallaxHeaderModeTopFill;
self.tableView.parallaxHeader.minimumHeight = 100.0f;
scrollView.parallaxHeader.mode = MXParallaxHeaderModeFill -> this line gives me the following error:
Use of unresolved identifier 'MXParallaxHeaderModeFill'
but i can cmd+click on the MXParallaxHeaderModeFill and still get the page where it's defined. am i doing something wrong everything else is working but i can't work without this line because the header image is squashed when i run. Please help. Danke!
if I set a minHeight higher then 0 progress should be calculated between minHeight (0) and maxHeight (1)
How to add the image icon with text on the segmented control instead of text
Can MXParallaxHeader be used with UIRefreshController?
I tried with UITableview with no success, but maybe you know a way to make it work.
With MXScrollViewController is there a way to put the NavegationBar over the parallaxHeader? What I mean is to have the parallaxHeader top constraint start at the NavegationBar top
I have implemented the MXParallaxHeader using storyboard and I need to refresh my tableview or collectionview with updated datasource but I didn't find any controller reference like any delegate method which gives us the selected controller so that I can call that methods please help me to fix this thanks
Is there a way to take into account the navbar height when setting the parallaxHeader.
What I mean is to have the parallaxHeader top constraint start at the NavBar bottom
@maxep Could you add the following code to ignore contentOffset
observe when mode is MXParallaxHeaderModeBottom
?
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (_mode == MXParallaxHeaderModeBottom) {
return ;
}
xxxx
}
The ParallaxHeader
flashes when I add pull to refresh
for tableView. if ignore contentOffset observe
when mode is MXParallaxHeaderModeBottom, it works ok.
self.headerImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, HEADERHEIGHT)];
self.headerImageView.image = [UIImage imageNamed:@"header-background"];
self.headerImageView.contentMode = UIViewContentModeScaleAspectFill;
UIImage *avatarImage = [UIImage imageNamed:@"avatar-placeholder"];
self.avatarImageView = [[UIImageView alloc]initWithFrame:CGRectMake(30, (HEADERHEIGHT - avatarImage.size.height)/2,avatarImage.size.width ,avatarImage.size.height )];
self.avatarImageView.image = avatarImage;
self.avatarImageView.layer.cornerRadius = avatarImage.size.height/2;
[self.headerImageView addSubview:self.avatarImageView];
self.profileTableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) style:UITableViewStylePlain];
self.profileTableView.parallaxHeader.view = self.headerView;
self.profileTableView.parallaxHeader.height = HEADERHEIGHT;
self.profileTableView.parallaxHeader.mode = MXParallaxHeaderModeFill;
self.profileTableView.parallaxHeader.minimumHeight = MINHEADERHEIGHT;
but the avatarImageView does not move with the headerview
*** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <(null) 0x0> for the key path "contentOffset" from <MXParallaxView 0x149415ff0> because it is not registered as an observer.'
Class "MXParallaxView",remove observer wrong,when dealloc
This is a very well library.
However, one has a big problem.
When you click on the last item first click is ignored.
It can be found in the MXScrollView of demo app.
It seems that the problem is related to the priority of gesture that occurs when there is another UIScrollView inside the UIScrollView.
Tested : iPhone 6S+ device or simulator
If we modify the sample project to return less cells than the size of screen, for example 2, and we setup a minimumHeight, like:
self.scrollView.parallaxHeader.minimumHeight = 100;
Then there is a weird behaviour in the header, see video.
At the moment I didn't have time to research, will do that later.
Pod files have changed in version 1.0
[!] Invalid `Podfile` file: [!] Unsupported options `{:exclusive=>true}` for target `MXParallaxHeader-Swift`.. Updating CocoaPods might fix the issue.
Your pod can't be used until this is fixed.
Hey there! Great work! I was trying to add a button to the headerView to dismiss the view controller but the button can't pick up any gestures. Any idea what's going on?
Hi thanks for your great control just want to add gestures to the headerviw how can we achieve that please tell me
Hi, I'm using auto layout with Masonry.
self.segmentedPager.parallaxHeader.view = self.headerView;
self.segmentedPager.parallaxHeader.mode = MXParallaxHeaderModeFill;
The header view has complex subviews , and is auto layout with Masonry.
There are some issue can not resolve by myself.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
MASLayoutConstraint:0x124e78970 UIImageView:0x126240dc0.height == 80",
MASLayoutConstraint:0x12630adc0 UILabel:0x126281610.height == 30",
MASLayoutConstraint:0x124e78870 UIImageView:0x126240dc0.centerY == ShopHeaderView:0x12625f020.centerY",
MASLayoutConstraint:0x12630ac50 UILabel:0x126281610.top == UIImageView:0x126240dc0.top + 4,
MASLayoutConstraint:0x126309c90 SKTagView:0x124e387b0.top == UILabel:0x126281610.bottom + 8",
MASLayoutConstraint:0x12630a3f0 SKTagView:0x124e387b0.bottom == ShopHeaderView:0x12625f020.bottom",
NSLayoutConstraint:0x12630ccf0 ShopHeaderView:0x12625f020.height == 0
)Will attempt to recover by breaking constraint
MASLayoutConstraint:0x124e78970 UIImageView:0x126240dc0.height == 80Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
Please help me. Thx.
Currently the child view scroll over the header.
Is there a way to make the header with child you?
Hi there, thanks for your great lib. I have an issue where I try to disable MXParallaxHeader to stick to minimumHeight. It's like this, header is full screen image and when I scroll it down I get "stuck" on minimumHeight. Can you help me to avoid this kind of behaviour?
This is my implementation:
scrollView.parallaxHeader.view = header
scrollView.parallaxHeader.minimumHeight = 0
scrollView.parallaxHeader.height = UIScreen.main.bounds.height
scrollView.parallaxHeader.mode = MXParallaxHeaderMode.center
scrollView.parallaxHeader.delegate = self
Bonjour @maxep,
J'utilise ta classe pour mon projet et j'en suis très satisfait. Cependant il y a un comportement étrange qui se retrouve également dans la démo (par exemple sur l'onglet MXScrollViewController). Si on scroll légèrement vers le bas et qu'on arrête le scroll avant que le header soit entièrement caché, impossible de scroller vers le haut avant de scroller un peu plus vers le bas pour "débloquer" le scroll vers le haut.
J'espère que mon explication est assez claire. Je n'arrive pas à voir d'où cela peut venir...
Merci d'avance pour ton aide.
Which version that can used with Swift version 1.2 ? Can u help point it. Thanks
I embedded the Scroll View Example (Swift example) in a NavigationController with its Navigation Bar hidden. With this setup, the header view sits just under the status bar, but doesn't extend below it. However, the scroll view content is still visible at the top, as can be seen in the picture below.
My header loads with a specific height, then I fetch the user data on server and load all informations about the user.
I need to change the header size after all informations are ready.
I tried to use self.segmentedPager.parallaxHeader.height = CGRectGetHeight(headerBoxView.bounds);
but didn't work
the CGRectGetHeight(headerBoxView.bounds
returns the right height, but the header doesn't change
[headerBoxView setNeedsLayout];
self.segmentedPager.parallaxHeader.height = CGRectGetHeight(headerBoxView.bounds);
[self.segmentedPager reloadData];
[self.segmentedPager layoutIfNeeded];
[self.view layoutIfNeeded];
Installed MXParallaxHeader from carthage and I get this error:
[UITableView parallaxHeader]: unrecognized selector sent to instance 0x7ff0ad872200
Cocoapods version seems to be ok
Hi,
I have added a basic MXSegmentedPagerController with two pages with a Table and Web Controller and it is crashing right away with this error. 'NSInvalidArgumentException', reason: '*** setObjectForKey: object cannot be nil (key: 0)'
. if i debug i crash occurs inside this method "[self.pager reloadData] "
I have attached the sample project on this. So I hope someone can resolve this. The MXParallaxHeader looks amazing however if i can't use it in Swift , then there is no point.
MXParallaxView-Swift.zip
When I use MXParallaxHeader on İOS9 it shows correct and works great. However when I open the same app in iOS 10 header shows a blank view. Does anybody have the same issue?
If I add a view to the tableView (which is a scrollView), it is always behind the header, even if I force it moving to the front.
In file MXParallaxView.m, method layoutContentView, I see the lines:
// Keep table header view over sections
[self.scrollView bringSubviewToFront:self.contentView.superview];
If I comment that line, it is working properly, even with a table that has sections.
So, I don't understand the purpose of that line.
Can we remove it or is there a edge case I don't see?
Thanks.
Hi,
When I use [self.navigationController pushViewController:vc animated:YES]; it pretty much doesn't work, not sure why? I'm not using storyboards.
Any help will be appreciated.
Nice library !
Please add Carthage support to this project.
I tried with setContentOffset but it doesn't work.
[self.scrollView setContentOffset:CGPointMake(0, -self.scrollView.contentInset.top)];
Thanks!
Crash on
this is my error :
Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <(null) 0x0> for the key path "contentOffset" from <MXParallaxView 0x1569c8860> because it is not registered as an observer.'
*** First throw call stack:
(0x180a42db0 0x1800a7f80 0x180a42cf8 0x1813590a8 0x181358b84 0x181358ac8 0x100ddaf80 0x185eb4014 0x185b994a0 0x185b9c924 0x181396cb0 0x1800c1ae8 0x1809209fc 0x1809f6bc0 0x180920c50 0x182208088 0x185c0a088 0x100281a58 0x1804be8b8)
libc++abi.dylib: terminating with uncaught exception of type NSException
With normal ScrollView work but when I try use MXScrollView i can't scroll the view
Then MXScroll content is a UICollectionView.
I have dragged the collectionView reducing the header space.
And I drag the collectionView downwards , sometimes my action doesn't work.
It is frozen except I drag the collection view upwards first.
Thank you for accepting the Pull request. I'm happy to contribute.
You could kindly generate a new version of CocoaPods?
I have a UIViewController with a UITableView subview filling the container.
I'm adding an imageView to be the header (I've tried this a few ways, including following the sample project) and can't get the library working.
let imageView = UIImageView()
imageView.image = UIImage(named: "placeholder_lg")
// Parallax Header
tableView.parallaxHeader.view = imageView
tableView.parallaxHeader.height = 300
tableView.parallaxHeader.mode = .fill
tableView.parallaxHeader.minimumHeight = 20
On view load, the scrollViewDidScroll function is called 4 times and the progresses are:
2016-10-26 11:09:49.388412 fm[1614:1068827] progress 0.000000
2016-10-26 11:09:49.389333 fm[1614:1068827] progress 0.000000
2016-10-26 11:09:49.390372 fm[1614:1068827] progress 0.066667
2016-10-26 11:09:49.390943 fm[1614:1068827] progress 0.066667
After loading, the progress is always 0.003333 on scroll. At no point is the image (or any other view I try to put in the parallaxHeader) visible. Am I missing something obvious here?
Same result on iOS 9 and 10
I have tried from storyboard to turn off the bounce as we usually do, and also tried programmatically like these :
profileDetailScrollView.bounces = false
func scrollViewDidScroll(scrollView: UIScrollView) {
NSLog("progress %f", scrollView.parallaxHeader.progress)
if scrollView.contentOffset.y < 0 {
scrollView.contentOffset.y = 0
}
}
But these solutions are not working, please help.
There are several bugs regarding gestures or interaction like:
The reason is because when we scroll a lot, the parallax contentView is outside screen and does not send taps to its subviews, even if they are displaced to be presented in the screen again.
You can see that using Reveal:
If we swap parallax.contentView.frame.origin.y and parallax.view.frame.origin.y then it works, but of course that only works in Reveal. Doing that we will see how the components that are in the small part (defined by parallaxHeader.minimumHeight) would work again.
I tried to modify the lib to do something like that, but no luck at the moment.
Does anyone have any idea? This would make the tiny part interactive, which is important.
Where in the code can I disable the automatic closing of the header so that I can use MXParallaxHeader as just a regular header view that moves in sync with the scrollview offset with the still zoom in effect when pulling down?
I want refresh data when scroll table to top
but I can not do it ???
LPMineHeaderView *headerView = [LPMineHeaderView loadInstanceFromNib];
_tableView.parallaxHeader.view = headerView;
_tableView.parallaxHeader.height = 135;
_tableView.parallaxHeader.mode = MXParallaxHeaderModeFill;
Hi I'm using the my own scrollview as header
But It is not working.. I means It was not stretched
My header view is consists of UIView and UIScrollView not UIImageView
Could you anyone helping me?
here is my code
`import Foundation
import UIKit
class AdvScrollView : UIScrollView, UIScrollViewDelegate {
// 1
var viewObjects: [UIImageView]?
var numPages: Int = 0
//declaire indicator
var scrollIndicator = UIView()
var indicator = UIView()
// 2
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
isPagingEnabled = true
showsHorizontalScrollIndicator = false
showsVerticalScrollIndicator = false
scrollsToTop = false
delegate = self
}
// 3
func setup() {
guard let parent = superview else { return }
contentSize = CGSize(width: (frame.size.width * (CGFloat(numPages) + 2)), height: 520)
loadScrollViewWithPage(0)
loadScrollViewWithPage(1)
loadScrollViewWithPage(2)
var newFrame = frame
newFrame.origin.x = newFrame.size.width
newFrame.origin.y = 0
scrollRectToVisible(newFrame, animated: false)
//set Number of Pages
let pages : CGFloat
pages = CGFloat(self.numPages)
self.scrollIndicator = UIView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: 3))
self.indicator = UIView(frame: CGRect(x: 0, y: 0, width: frame.size.width / pages, height: 2))
self.scrollIndicator.backgroundColor = UIColor.black
self.indicator.backgroundColor = UIColor(red: 0.0/255, green: 109/255, blue: 242/255, alpha: 1)
parent.addSubview(scrollIndicator)
parent.addSubview(indicator)
//Set First Page
self.setContentOffset(CGPoint(x:0, y:0), animated: true)
layoutIfNeeded()
}
// 4
fileprivate func loadScrollViewWithPage(_ page: Int) {
if page < 0 { return }
if page >= numPages + 2 { return }
var index = 0
if page == 0 {
index = numPages - 1
} else if page == numPages + 1 {
index = 0
} else {
index = page - 1
}
let view = viewObjects?[index]
var newFrame = frame
newFrame.origin.x = frame.size.width * CGFloat(page)
newFrame.origin.y = 0
view?.frame = newFrame
if view?.superview == nil {
addSubview(view!)
}
layoutIfNeeded()
}
// 5
@objc internal func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageWidth = frame.size.width
let page = floor((contentOffset.x - (pageWidth/2)) / pageWidth) + 1
loadScrollViewWithPage(Int(page - 1))
loadScrollViewWithPage(Int(page))
loadScrollViewWithPage(Int(page + 1))
//Scrollview
let pages : CGFloat
pages = CGFloat(self.numPages)
if page >= 16 {
self.indicator.frame = CGRect(x: contentOffset.x / pages - 375, y: 0, width: frame.size.width / pages, height: 2);
}else {
self.indicator.frame = CGRect(x: contentOffset.x / pages, y: 0, width: frame.size.width / pages, height: 2);
}
}
// 6
@objc internal func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageWidth = frame.size.width
let page : Int = Int(floor((contentOffset.x - (pageWidth/2)) / pageWidth) + 1)
if page == 0 {
contentOffset = CGPoint(x: pageWidth*(CGFloat(numPages)), y: 0)
} else if page >= numPages+1 {
contentOffset = CGPoint(x: pageWidth, y: 0)
}
}
}
import Foundation
import UIKit
class AdvScrollView : UIScrollView, UIScrollViewDelegate {
// 1
var viewObjects: [UIImageView]?
var numPages: Int = 0
//declaire indicator
var scrollIndicator = UIView()
var indicator = UIView()
// 2
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
isPagingEnabled = true
showsHorizontalScrollIndicator = false
showsVerticalScrollIndicator = false
scrollsToTop = false
delegate = self
}
// 3
func setup() {
guard let parent = superview else { return }
//height 520 -> frame.size.height
contentSize = CGSize(width: (frame.size.width * (CGFloat(numPages) + 2)), height: frame.size.height)
loadScrollViewWithPage(0)
loadScrollViewWithPage(1)
loadScrollViewWithPage(2)
var newFrame = frame
newFrame.origin.x = newFrame.size.width
newFrame.origin.y = 0
scrollRectToVisible(newFrame, animated: false)
//set Number of Pages
let pages : CGFloat
pages = CGFloat(self.numPages)
self.scrollIndicator = UIView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: 3))
self.indicator = UIView(frame: CGRect(x: 0, y: 0, width: frame.size.width / pages, height: 2))
self.scrollIndicator.backgroundColor = UIColor.black
self.indicator.backgroundColor = UIColor(red: 0.0/255, green: 109/255, blue: 242/255, alpha: 1)
parent.addSubview(scrollIndicator)
parent.addSubview(indicator)
//Set First Page
self.setContentOffset(CGPoint(x:0, y:0), animated: true)
layoutIfNeeded()
}
// 4
fileprivate func loadScrollViewWithPage(_ page: Int) {
if page < 0 { return }
if page >= numPages + 2 { return }
var index = 0
if page == 0 {
index = numPages - 1
} else if page == numPages + 1 {
index = 0
} else {
index = page - 1
}
let view = viewObjects?[index]
var newFrame = frame
newFrame.origin.x = frame.size.width * CGFloat(page)
newFrame.origin.y = 0
view?.frame = newFrame
if view?.superview == nil {
addSubview(view!)
}
layoutIfNeeded()
}
// 5
@objc internal func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageWidth = frame.size.width
let page = floor((contentOffset.x - (pageWidth/2)) / pageWidth) + 1
loadScrollViewWithPage(Int(page - 1))
loadScrollViewWithPage(Int(page))
loadScrollViewWithPage(Int(page + 1))
//Scrollview
let pages : CGFloat
pages = CGFloat(self.numPages)
if page >= 16 {
self.indicator.frame = CGRect(x: contentOffset.x / pages - 375, y: 0, width: frame.size.width / pages, height: 2);
}else {
self.indicator.frame = CGRect(x: contentOffset.x / pages, y: 0, width: frame.size.width / pages, height: 2);
}
}
// 6
@objc internal func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageWidth = frame.size.width
let page : Int = Int(floor((contentOffset.x - (pageWidth/2)) / pageWidth) + 1)
if page == 0 {
contentOffset = CGPoint(x: pageWidth*(CGFloat(numPages)), y: 0)
} else if page >= numPages+1 {
contentOffset = CGPoint(x: pageWidth, y: 0)
}
}
}
class FeedVC: UITableViewController {
@IBOutlet var headerView: UIView!
//UI Objects
@IBOutlet weak var indicator: UIActivityIndicatorView!
var refresher=UIRefreshControl()
//Arrays to hold server data
var usernameArray = [String]()
var dateArray = [Date?]()
var postArray = [PFFile]()
var uuidArray = [String]()
var descriptionArray = [String]()
var commentsArray = [String]()
var commentsByArray = [String]()
let commnetLabel = ActiveLabel()
var isLoadedView:Bool = false
var sellingArray = [Bool]()
var followArray = [String]()
//page size
var page : Int = 10
//Default func
override func viewDidLoad() {
super.viewDidLoad()
//set parallaxHeader
// Parallax Header
tableView.parallaxHeader.view = headerView // You can set the parallax header view from the floating view
tableView.parallaxHeader.height = 524
tableView.parallaxHeader.mode = MXParallaxHeaderMode.fill
tableView.parallaxHeader.minimumHeight = 40
//background color
tableView?.backgroundColor = UIColor(red: 0.0 / 255.0, green: 0.0 / 255.0, blue: 0.0 / 255.0, alpha: 1)
//automatic row height
tableView.estimatedRowHeight = 450
tableView.rowHeight = UITableViewAutomaticDimension
}
`
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.