Jason’s original concept of a new dashboard interface for navigating the Khan Academy’s exercises has come to life(you’ll need an account).
My “Addition 1” skills are improving.
"Why did you do this?"
Since we started preparing to test out the Khan Academy’s exercises inside a couple forward-thinking schools, we knew we needed an interface that clearly shows students which exercises they should be working on and where progress has been made.
We also wanted to make the whole experience a bit more Mario 64fun.
We’re using a Google Maps-like interface for plenty of reasons, not the least of which is that Google has spent a lot of time trying to figure out how to build interfaces that help people navigate two(-ish)-dimensional maps. Piggy-backing on their work for our two(-ish)-dimensional map of knowledge concepts seems like a big win.
So far we have absolutely zero proof that we’ve accomplished (or failed at) any of this. But we will have lots of evidence or counterevidence soon(!), when students start using using this interface to navigate their math class.
All I know is that I keep fighting off my video gamer’s urge to turn this…
…into this, which must be a good sign.
"Before you guys have to revert all your changes because you underestimated your users’ astrophobia, how does this work?”
I’m going to share the technical details of using the Google Maps API (v3) to implement the map part.
The Custom Map
When you create a new google.maps.Map object, you can specify a number of preconfigured map types (like ROADMAP
,SATELLITE
, etc). None of these worked for us since we needed a blank slate on which to draw our own map. The Maps API does support creating completely custom maps, but even their tutorial has all types of “This is an advanced topic,” “We didn’t fully document this process,” “This is more difficult than it sounds”-type warnings.
Luckily, Google has given us a customizable google.maps.ImageMapType
which implements all of the hairy details of a custom map and only requires that you implement one function which basically boils down to, “Given a specific latitude, longitude, and zoom level, what image should the map display?” PERFECT. This is exactly what we needed. I started off by always returning some /images/black_tile.png
URL to just get a big black blank slate of a map.
var knowledgeMapType = new google.maps.ImageMapType(this.options);
this.map.mapTypes.set('knowledge', knowledgeMapType);
this.map.setMapTypeId('knowledge');
...
getTileUrl: function(coord, zoom) {
return "/images/black_tile.png"
},
Setting up controls
The API is really pleasant to use. When setting up your map, there are are options like streetViewControl: false
for all types of control settings and positions. We turned off Street View, restricted zoom to a few particular levels, added the pan and zoom control in the upper left, and made a few other tweaks. A primary reason for choosing Google Maps as the tool to represent our knowledge map was getting well-behaved pan, zoom, and more in an extremely stable cross-browser package.
this.map = new google.maps.Map(document.getElementById("map-canvas"), {
mapTypeControl: false,
streetViewControl: false,
scrollwheel: false
});
Placing and labeling nodes
Each node represents one module of the Khan Academy exercises. Google makes it easy to throw markers with customized icons on their maps at specific lat/long coordinates. However, there’s no simple built-in way to label the icons with text. I used a little external utility, markerwithlabel.js, to get this functionality.
var marker = new MarkerWithLabel({
position: node.latLng,
map: this.map,
icon: this.getMarkerIcon(iconUrl, zoom),
flat: true,
labelContent: node.name,
labelAnchor: this.getLabelAnchor(zoom),
labelClass: this.getLabelClass(labelClass, zoom)
});
Going into space
Once the map really started to come together we wanted more than a plain black background. We’d be missing out on one of the coolest pieces of Google Maps if we didn’t take advantage of some cool tile zooming behavior. We totally lucked out when realizing that we could use Google Sky. It’s really easy to make that “turn Latitude/Longitude/Zoom into a tile URL” function I mentioned above grab the appropriate Google Sky tiles.
getTileUrl: function(coord, zoom) {
// Sky tiles example from
// http://gmaps-samples-v3.googlecode.com/svn/trunk/planetary-maptypes/planetary-maptypes.html
return KnowledgeMap.getHorizontallyRepeatingTileUrl(coord, zoom,
function(coord, zoom) {
return "http://mw1.google.com/mw-planetary/sky/skytiles_v1/" +
coord.x + "_" + coord.y + '_' + zoom + '.jpg';
}
)}
Now when students are zooming in and out of their knowledge map they’re also zooming in and out of actual Hubble photos of outer space. Google’s APIs gave us all of this power in about 5 minutes.
Saving the user’s last coordinates
If the knowledge map is going to help students understand where they are in the collection of Khan Academy exercises, it needs to remember their last position. On the server we have a URL that can save each user’s current latitude, longitude, and zoom level. I started off by listening for our map’s center_changed
and zoom_changed
events to detect any change in position and send off a fire’n’forget request to save state on the server. Bad: these events fire constantly while dragging around the map. Good: listening for the idle
event instead, which fires when map movement has settled, works perfectly.
google.maps.event.addListener(this.map, "idle", function(){KnowledgeMap.saveMapCoords();});
...
saveMapCoords: function() {
var center = this.map.getCenter();
$.post("/savemapcoords", {
"lat": center.lat(),
"lng": center.lng(),
"zoom": this.map.getZoom()
}); // Fire and forget
}
Preventing students from getting lost in space
There’s a lot more Google Sky than there are Khan Academy modules (for now), so we needed to restrict the movement of the map to protect users from getting lost at random positions in space that are nowhere near the module nodes. In this case the constantly-firing center_changed event
is perfect. We listen for changes and update the center of the map whenever it has been dragged “out of bounds.”
google.maps.event.addListener(this.map, "center_changed", function(){KnowledgeMap.onCenterChange();});
...
onCenterChange: function() {
var center = this.map.getCenter();
if (this.approvedBounds.contains(center)) {
return;
}
else {
// Restrict to approved boundary
}
}
Changing the size of icons and labels on zoom
Markers (and MarkerWithLabels) don’t normally change sizes when the map zooms. To accomplish this, we listen to the zoom_changed
event, update the icon and label properties appropriately for each zoom level, and force the markers to redraw. I know there are other options here instead of using markers, but markers make a lot of sense when laying out nodes programmatically. This also means we get to add cool zoom-y easter eggs like Constellation View.
google.maps.event.addListener(this.map, "zoom_changed", function(){KnowledgeMap.onZoomChange();});
...
onZoomChange: function() {
var zoom = this.map.getZoom();
for (var key in this.dictNodes)
{
var node = this.dictNodes[key];
var marker = node.marker;
marker.setIcon(this.getMarkerIcon(node.iconUrl, zoom));
marker.labelAnchor = this.getLabelAnchor(zoom);
marker.labelClass = this.getLabelClass(marker.labelClass, zoom);
marker.label.setStyles(); // Redraw marker's label
}
}
Please take a look
Most of the work is in knowledgemap.js. You’ll notice that the snippets above have been simplified. I’m 100% positive there are more elegant ways to do most of this stuff. Let me know when you find them.
We had fun working on this UI, but there’s so much to do in so many other areas of the Khan Academy that we can’t get stuck in any one spot for long. Sal and Shantanu have gotten lots of great feedback from teachers and parents already, and it’s clear that they’ll need better reporting tools soon. Moving quickly is one of our most important goals.
"I caught you playing a video game!"
Rebecca walked into my room yesterday while I was working on this UI, and she totally called me out for playing a video game in my second week of work. I had a huge smile on my face for minutes.
相关推荐
《翻转课堂的可汗学院》读书心得 ...《翻转课堂的可汗学院》是一本关于教育革命的书籍,提出了微课程教学法的概念和实施方法,旨在优化课堂时间,提高教学效率,促进学生的自主学习和教师的职业发展。
khan-exercises, 用于构建与 可汗学院 一起工作的练习的( 已经废弃) 框架 可汗学院 练习可汗学院 为构建练习创建了一个通用框架。 这个框架和练习本身,可以完全独立于 可汗学院 应用程序使用。这里 repo 由两个部分...
他于2009年辞去金融分析师的工作,专心建设这一旨在为全球学生提供免费在线教育的“可汗学院”。2014年1月,YouTube上的“可汗学院频道”共吸引了163.3万订阅者,观看次数超过3.55亿次。萨尔曼·可汗已成为教育领域...
[电子书] 翻转课堂的可汗学院 互联时间的教育革命....
网易公开课, 可汗学院 统计学第28课 正态分布excel的练习。
【可汗学院逻辑问题解析】 可汗学院是一个知名的在线学习平台,由萨尔曼·可汗创立,旨在提供免费的教育资源,涵盖数学、科学等多个领域。在其逻辑问题中,常常设计出一些需要深入思考和策略解答的智力挑战。以下...
微观经济学 一份具详细的一看就懂的学习笔记,课程From 网易公开课 可汗学院 公开课
5. **家长的角色**:家长可以通过先观看可汗学院的视频,了解其教学方法,然后模仿可汗的方式亲自给孩子讲解,这样既能够确保孩子理解概念,又能增进亲子间的互动。 6. **适合的学习阶段**:可汗学院的算术与代数...
总的来说,宏观经济学通过具体的案例和模型,让我们了解了GDP的基本概念、计算方法以及其在经济分析中的作用。它不仅帮助我们认识国家经济的整体表现,也为政策制定者提供了衡量经济健康状况和制定经济政策的依据。...
可汗学院_7.6.1.apk.1s
在可汗学院的现有或,复制所需构建类型的代码。 CDN 通过jsDelivr CDN从外部加载Essentials,就可以使用它。 使用以下可以使用其他受限制的功能。 // jshint ignore: start 使用的方法加载库。 $ . ajaxSetup ( {...
文档可汗学院API: : 使用方法: 为了支持针对Khan Academy API的多个身份验证会话以及不同的语言设置,对API的每次调用都通过Khan()会话完成。 from api_models import * 默认情况下,lang设置为“ en”,...
可汗学院PyCharm插件 PyCharm IDE的插件,供可汗学院的开发人员使用。 当前,它具有一项功能: 它用类似的菜单选项替换了常规的“运行测试”上下文菜单选项,这些菜单选项创建了与Khan Academy的测试基础结构兼容...
感染这是我对可汗学院感染面试问题的解决方案。运行代码JAR 文件 (khanacademy-infection.jar) 是存储库的一部分。 运行模拟的最简单方法是下载此文件并使用 Java 运行。 该代码是一个 IntelliJ IDEA 项目,因此 git...
可汗学院,一个知名的在线教育平台,提供了一系列的文章来教授这些知识,旨在让学习者掌握计算思维和编程能力。在"computing-curriculum"这个资源中,我们可以期待深入学习与HTML相关的编程概念。 HTML,全称...
《可汗学院颜色资源在OS X系统中的应用与配置》 可汗学院,作为一个全球知名的在线教育平台,不仅以其丰富的教学资源闻名,还注重用户体验的细节。在OS X操作系统中,用户可以发现一个名为“KhanAcademy_clr”的...
可汗学院练习的仪表板在地图上实时完成! 设置 要设置为本地开发,只需启动一个本地服务器服务于项目目录: python -m SimpleHTTPServer 托管在,因此只需推送到gh-pages分支即可自动发布站点。
可汗学院的Chrome扩展程序 可汗学院的Chrome扩展程序。加入我们的Discord,以获取项目更新:https://discord.gg/Bhd9FjN功能:*实时编辑器设置,具有多个主题,制表符/空格间距和自动完成功能*复制链接按钮可复制...
这个扩展将实现可汗学院的tota11y JS文件 所有学分可汗学院和他们的真棒剧本。这个扩展只是在所有页面上加载脚本。有关更多详细信息,请参阅http://khan.github.io/tota11y/。 v0.1.5 - 6/29/2016 - 将脚本更新为...
KA-程序这个存储库用于组织、备份和版本控制我使用可汗学院的计算机科学环境创建的一些程序。 我的课程的完整列表可在: : 文件显示为 JS 文件,但需要 Processing.js 和此处所述的一些更改: : 每个文件的第一行是...