๐ฅ ไป็ป่ง้ข | Intro Video
็ซๆ ็ช็ถ่่ณ๏ผๆ็ ดไบๅๆฌ็ๅญฆๆ ก็ๆดป๏ผไนๆ็ ดไบๆไปฌ่ฎฐๅฝ็ๆดป็ๆนๅผ
ไปblogๅฐvlog๏ผไบบไปฌ่ฎฐๅฝ็ๆดป็ๆนๅผๅจไธๆญไธฐๅฏ
ๆตยทๅฟ โโ ๅฐ่ฏไปๅ จๆฐ่ง่งๅ็ฐ่บซ่พน็็พ
๐ธ ็จๅ จๆฏ่ฎฐๅฝ็ๆดป
- ๅๆตๆฅๅ
- ๆฅ็ๆๅนดๆๆๆฅๅไฟกๆฏ
- ๅๅป้ผ ๆ ๅๆขๆฅๆ
- ๅๅปๆฅๆไธไผ ๅพ็ๅนถๆทปๅ ๅๅฟ
- ๅ จๆฏๆผๆฅ๏ผๅฏไปฅไธไผ 1๏ฝ3ๅผ ็ ง็๏ผๅๅฐไผ่ฟ่กๅ จๆฏๆผๆฅ๏ผๅ จๆฏๆผๆฅ็ฎๆณ้่ฆๆปก่ถณๅพ็ๆฌ่บซไฝไบๅไธๅนณ้ข็ญ๏ผๅฏ่ฝไธ่ฝๅฎ็พๆผๆฅ๏ผ
- ๅๆตๅฐ่ฎฐ๏ผไปฅ็พๅถ็ช็ๅฝขๅผๅฑ็คบๆๆๅๅฟ
- ๅ
จๆฏๆผซๆธธ
- ๆๅจ้ผ ๆ ่ฟ่กๅบๆฏๆผซๆธธ
- ๅๅปๆทปๅ ๅๅฟ
- ๅๅป้ผ ๆ ๅณ้ฎๅๆขๆๅญๆ ็ญพๅๅพๆ ๆ ็ญพ
- ้ผ ๆ ๆป่ฝฎ่ฟ่กๅบๆฏ็ผฉๆพ
- ้้ ๆๆบ็ซฏ่งฆๆธไบไปถ
- ็้ขๅฏผ่ช
- ๅ ถไธญๅฎๅไบใๅๆตๅๅใๅนถไฝไธบๅญ็ณป็ป
- ๆณจๅ / ็ป้
- ๅชไฝไฟกๆฏ๏ผgithub๏ผ้ฎ็ฎฑ๏ผ่ง้ข๏ผๆๆกฃ๏ผ
- ๅไบซ
- ๅพฎไฟก๏ผ้่ฆ็จๆต่งๅจๆซ็ ๏ผ
- qq็ฉบ้ด
- ๅพฎๅ
- ็นๆ
- svgๆณขๆตช็นๆ
- ๅจๆๅ ่ฝฝๆตไฝ็นๆ
- CMSๅจๆไฟฎๆน็ฝ็ซๅ ๅฎน๏ผไธ้่ฆๅๆฌก้จ็ฝฒ๏ผ
- ๆฐๆฎๆไน ๅ
- ่ฟ็จ้จ็ฝฒ๏ผtj-memory.doublez.site
- ้้ PC ๅนณๆฟ ๆๆบ็ญไธๅๅนณๅฐ
-
ๆไฝ็ณป็ป
- ๅผๅ็ฏๅข๏ผmacOS Catalina 10.15.4
- ้จ็ฝฒ็ฏๅข๏ผUbuntu 16.04.6 LTS
-
IDE
- Visual Studio Code 1.45.1
- IntelliJ IDEA 2019.3.2
- PyCharm 2019.3.2
-
ๅผๅ่ฏญ่จ
- HTML5
- CSS3
- JavaScript
- Java
- python
-
**ๆฐๆฎๅบ **: mysql 8.0.20
-
ๆกๆถๆๆฏ
-
ๅ็ซฏ๏ผ
- ๅ็HTML + CSS + JavaScript
- three.js
โ ไป ๆไธๅคไฝฟ็จVueๆกๆถ๏ผไธป่ฆไธบไบๅ จๆน้ขๅญฆไน
-
ๅ็ซฏ๏ผSpringBoot + Maven + Mysql + MyBatis
-
-
ไธป่ฆไพ่ต: opencv-python
ๅ ถไธญๆถๅๅฐ็ๆฌ้ฎ้ข๏ผ็ฏๅข้่ฆ่ฟ่กๅฆไธ้ ็ฝฎ
pip uninstall opencv-python pip install opencv-python==3.4.2.16 -i "https://pypi.doubanio.com/simple/" pip install opencv-contrib-python==3.4.2.16 -i "https://pypi.doubanio.com/simple/"
-
CMS: Contentful
้จๅๅพ็่ตๆบๆฅ่ช็ฝ็ป๏ผไพตๅ
ๆ ธๅฟๅฎ็ฐ
function getEntries_by_ContentType(client, content_type){
return new Promise(resolve => {
client.getEntries({
content_type: content_type
})
.then((response) => {
resolve(response);
})
.catch(console.error);
});
}
let response = await getEntries_by_ContentType(client, 'tjMemoryHero');
let heroObj = response.items[0].fields;
this.styleObject.backgroundImage = "url(" + "https:" + heroObj.bg.fields.file.url + ")";
ๆฅๅๆ ธๅฟ้จๅๅ จ้จ็ฑJavaScript่ฟ่กๅจๆ็ๆ
<div id="CalendarGroup" class="CalendarGroup">
<div class="awesome-calendar">
<div class="header" style="grid-area: header;">
<div class="left-part">
<div id="year-left" class="nev"><<</div>
<div id="month-left" class="nev"><</div>
</div>
<h1 id="current-year-month">November<br />2017</h1>
<div class="right-part">
<div id="month-right" class="nev">></div>
<div id="year-right" class="nev">>></div>
</div>
</div>
<div id="weeks" class="weeks" style="grid-area: weeks;">
<!-- <div class="week" style="grid-area: Monday;">Monday</div> -->
</div>
<div id="days" class="days" style="grid-area: days;">
</div>
</div>
</div>
function printDays(year, month) {
refresh();
isExistArray = [];
var nowMonthStartDay = new Date(year, month - 1, 1).getDay(); //ๅฝๅๆ็ฌฌไธๅคฉๆฏๅจๅ
if(nowMonthStartDay == 0) {
nowMonthStartDay = 7;
}
var numberOfDaysInMonth = new Date(year, month, 0).getDate(); //ๅฝๅๆๆๅคๅฐๅคฉ
now.innerHTML = " ";
now.innerHTML = monthLetter[month - 1] + '<br />' + year; //ๆนๅtitle็ๅ
ๅฎน
if(sessionStorage.getItem("isLogin") === "true"){
startLoader(); // ๅฏๅจๆตไฝloader
let calendarInfo = {
"username": sessionStorage.getItem("username"),
"picyear": changeYear,
"picmonth": changeMonth + 1,
};
connectToBackEnd(calendarInfo, "calendar")
.then(result => {
stopLoad(); // ๅๆญขๆตไฝloader
obj = [];
if(result['state'] === 'true'){
obj = result["photos"];
initHistory(result["photos"]);
for(var i = 1, j = nowMonthStartDay; i <= numberOfDaysInMonth; i++, j++) { //ๅคๆญๅ่ฒ็ๆฅๆ
var DayText = $("day" + j);
var DayBgColor = DayText;
if(isAwesome){
DayText = $("day-text-" + j);
DayBgColor = $("day-bgcolor-" + j);
}
let existItem = isExist(obj, changeYear, changeMonth+1, j);
if(existItem != false){
isExistArray.push(j.toString());
$("day-description-" + j).innerHTML = existItem.description;
setStyle(DayBgColor, {
background: "url(" + existItem.imgbase.replace(/[\r\n]/g,"") + ")",
backgroundSize: "cover",
backgroundPosition: "center",
});
}
DayText.innerHTML = "" + i;
if(year == thisYear && month == thisMonth && i.toString() == dayNum) { //ๅฝๅๆฅๆไธ็ดๆฏ็บข่ฒ
setStyle(DayBgColor, {
background: '#E96D71'
});
}
if(i.toString() == changeDay) { //้ไธญ็็ฌฆๅ่ฆๆฑ็ๆฅๆๆพ็คบ็ปฟ่ฒ
DayBgColor.style = "background:#1abc9c";
let freshDay = new Date(changeYear, changeMonth-1, changeDay);
let weekNum = (freshDay.getDay() + 7 - 1) % 7;
if(weekNum === 6) {
$("week-bg").style.left = "calc(calc(calc(var(--button-width) + var(--week-padding))*" + weekNum + ") - calc(var(--week-padding)*0.5))";
} else {
$("week-bg").style.left = "calc(calc(var(--button-width) + var(--week-padding))*" + weekNum + ")";
}
}
}
} else {
alert(result['msg'] + "ๅ ่ฝฝๅๆตๆฅๅ๏ผ่ฏทๅทๆฐๅฐ่ฏ");
}
})
.catch(error => console.log(error));
}
myinput.onchange = function (){
// TODO ็จๆท้ๆฉๅฅฝๆไปถ็นๅป็กฎๅฎ
let imageType = /^image\//;
if(this.files.length){
var _description = prompt("่ฏท่พๅ
ฅไฝ ็ๅๅฟๆ่ฟฐ");
if(_description==null || _description==""){
alert("่พๅ
ฅ็ๅๅฟไธ่ฝไธบ็ฉบ");
return;
}
event.target.parentElement.nextElementSibling.firstElementChild.innerHTML = _description;
isExistArray.push(now.day.toString());
/******* ๅคๅผ ๅพ็ๅค็้ป่พ *********/
let fileappidx = null;
let total = this.files.length;
counter = 0;
for(var i=0; i<this.files.length; ++i){
let file = this.files[i];
fileappidx = file.type.substring(file.type.indexOf("/")+1);
let reader = new FileReader();
if (!imageType.test(file.type)) {
alert("่ฏท้ๆฉๅพ็, ่ฏฅ็ฑปๅ็ๆไปถไธๅๆฏๆ!");
return;
}
let imgbase64 = reader.result;
//ๆฐๅปบ FileReader ๅฏน่ฑก
reader.onload = function(){
counter ++;
let _imgname = getIndexStr(now.year) + "-" +
getIndexStr(now.month) + "-" +
getIndexStr(now.day) + "." + fileappidx;
let data_from_front = {
username: sessionStorage.getItem("username"),
picyear: now.year,
picmonth: now.month,
picday: now.day,
description: _description,
imgbase: this.result,
imgurl: sessionStorage.getItem("username") + "/" + _imgname,
index: counter,
length: total,
};
let itemBg = event.target.previousElementSibling.firstElementChild;
setStyle(itemBg, {
background: "url(" + this.result + ")",
backgroundSize: "cover",
backgroundPosition: "center",
});
connectToBackEnd(data_from_front, "add_picture")
.then(result => {
if(result['state'] === 'true'){
obj.push({
description: data_from_front.description,
picyear: data_from_front.picyear,
picmonth: data_from_front.picmonth,
picday: parseInt(data_from_front.picday),
username: data_from_front.username,
imgbase: this.result,
picurl: data_from_front.imgurl
});
} else {
alert(result['msg'] + "ๆทปๅ ๅพ็ๅคฑ่ดฅ๏ผ่ฏทๅทๆฐๅฐ่ฏ");
}
})
.catch(error => console.log(error));
};
reader.readAsDataURL(file); //ไปฅbase64ๆนๅผ่ฏปๅๆไปถ
}
/******* END ๅคๅผ ๅพ็ๅค็้ป่พ *********/
}
};
(่ฟ้ไฝ้ๆฏ่พๅบๅคง๏ผๅฏไปฅๅ็tpanorama.js)
opt = {
container: 'panoramaConianer',//ๅฎนๅจ
url: '../db/' + imgurl ,
lables: _lables,
widthSegments: 60, //ๆฐดๅนณๅๆฎตๆฐ
heightSegments: 40, //ๅ็ดๅๆฎตๆฐ๏ผๅผๅฐ็ฒ็ณ้ๅบฆๅฟซ๏ผๅผๅคง็ฒพ็ป้ๅบฆๆ
ข๏ผ
pRadius: 1000, //ๅ
จๆฏ็็ๅๅพ๏ผๆจ่ไฝฟ็จ้ป่ฎคๅผ
minFocalLength: 6, //้ๅคดๆๅฐๆ่ฟ่ท็ฆป
maxFocalLength: 100, //้ๅคดๆๅคงๆ่ฟ่ท็ฆป
sprite: 'label', // label,icon
onClick: (e) => {
console.log(e.object.name);
}
};
tp = new tpanorama(opt);
tpanorama.prototype = {
constructor: this,
def: {},
render: function (opt) {
this.def = extend(options, opt, true);
document.getElementById(this.def.container).innerHTML = '';
_lables = [];
initContainer(this.def.container);
initCamera();
initRaycaster();
makePanorama(this.def.pRadius, this.def.widthSegments, this.def.heightSegments, this.def.url);
initRenderer();
initLable(this.def.lables, this.def.sprite);
_container.addEventListener('dblclick', mydblClickHandler, false);
_container.addEventListener('touchstart', mydblTouchHandler, false);
_container.addEventListener('mousedown', onRightClickHandler, false);
document.oncontextmenu = function(e){
e.preventDefault();
return false;
};
_container.addEventListener('mousedown', onDocumentMouseDown, false);
_container.addEventListener('mousemove', onDocumentMouseMove, false);
_container.addEventListener('mouseup', onDocumentMouseUp, false);
_container.addEventListener('touchstart', onDocumentTouchStart, false);
_container.addEventListener('touchmove', onDocumentTouchMove, false);
_container.addEventListener('touchend', onDocumentTouchEnd, false);
_container.addEventListener('mousewheel', (e) => {
onDocumentMouseWheel(e, this.def.minFocalLength, this.def.maxFocalLength);
}, false);
_container.addEventListener('DOMMouseScroll', (e) => {
onDocumentMouseWheel(e, this.def.minFocalLength, this.def.maxFocalLength);
}, false);
_container.addEventListener('click', onDocumentMouseClick.bind(this), false);
global.addEventListener('resize', onWindowResize, false);
animate();
}
};
@Controller
@ComponentScan({"site.doublez.tjmemory.service"})
@MapperScan("site.doublez.tjmemory.dao")
public class CalendarController {
@Resource
private PythonConnectorService pythonConnectorService;
@Resource
private PhotoService photoService;
@PostMapping("/calendar")
@ResponseBody
public Map<String, Object> History(@RequestBody Map<String,Object> map) throws ParseException {
String username = map.get("username").toString();
int picyear = Integer.parseInt(map.get("picyear").toString());
int picmonth = Integer.parseInt(map.get("picmonth").toString());
Map<String, Object> result_map = new HashMap<>();
try {
ArrayList<Photo> photoArrayList = photoService.select_photos_by_year_month(new DayInfo(username, picyear, picmonth));
result_map.put("photos", photoArrayList);
result_map.put("state", "true");
} catch (Exception e){
e.printStackTrace();
result_map.put("state", "false");
result_map.put("msg", "ๆฐๆฎๅบ้่ฏฏ");
}
return result_map;
}
}
@Mapper
public interface PhotoDao {
void insert_photo(Photo photo);
ArrayList<Photo> select_photos_by_year_month(DayInfo dayInfo);
Photo select_photo_by_date(DayInfo dayInfo);
}
@Data
public class Photo {
private int id;
private String username;
private int picyear;
private int picmonth;
private int picday;
private String imgbase;
private String description;
private String picurl;
}
@Service("labelService")
@ComponentScan({"site.doublez.tjmemory.dao"})
public class LabelService {
@Resource
private LabelDao labelDao;
public void insert_label(Label label){
labelDao.insert_label(label);
}
public ArrayList<Label> select_label(String username, int picyear, int picmonth, int picday){
return labelDao.select_label(new DayInfo(username, picyear, picmonth, picday));
}
}
def full_view(filename1, filename2, dirname):
leftgray, rightgray = cv2.imread(dirname + filename1), cv2.imread(dirname + filename2)
hessian = 400
surf = cv2.xfeatures2d.SURF_create(hessian) # ๅฐHessian Threshold่ฎพ็ฝฎไธบ400,้ๅผ่ถๅคง่ฝๆฃๆต็็นๅพๅฐฑ่ถๅฐ
kp1, des1 = surf.detectAndCompute(leftgray, None) # ๆฅๆพๅ
ณ้ฎ็นๅๆ่ฟฐ็ฌฆ
kp2, des2 = surf.detectAndCompute(rightgray, None)
FLANN_INDEX_KDTREE = 0 # ๅปบ็ซFLANNๅน้
ๅจ็ๅๆฐ
indexParams = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) # ้
็ฝฎ็ดขๅผ๏ผๅฏๅบฆๆ ็ๆฐ้ไธบ5
searchParams = dict(checks=50) # ๆๅฎ้ๅฝๆฌกๆฐ
# FlannBasedMatcher๏ผๆฏ็ฎๅๆๅฟซ็็นๅพๅน้
็ฎๆณ๏ผๆ่ฟ้ปๆ็ดข๏ผ
flann = cv2.FlannBasedMatcher(indexParams, searchParams) # ๅปบ็ซๅน้
ๅจ
matches = flann.knnMatch(des1, des2, k=2) # ๅพๅบๅน้
็ๅ
ณ้ฎ็น
good = []
# ๆๅไผ็ง็็นๅพ็น
for m, n in matches:
# if m.distance < 0.7 * n.distance: # ๅฆๆ็ฌฌไธไธช้ป่ฟ่ท็ฆปๆฏ็ฌฌไบไธช้ป่ฟ่ท็ฆป็0.7ๅๅฐ๏ผๅไฟ็
if m.distance < 0.3 * n.distance:
good.append(m)
src_pts = np.array([kp1[m.queryIdx].pt for m in good]) # ๆฅ่ฏขๅพๅ็็นๅพๆ่ฟฐๅญ็ดขๅผ
dst_pts = np.array([kp2[m.trainIdx].pt for m in good]) # ่ฎญ็ป(ๆจกๆฟ)ๅพๅ็็นๅพๆ่ฟฐๅญ็ดขๅผ
H = cv2.findHomography(src_pts, dst_pts) # ็ๆๅๆข็ฉ้ต
h, w = leftgray.shape[:2]
h1, w1 = rightgray.shape[:2]
shft = np.array([[1.0, 0, w], [0, 1.0, 0], [0, 0, 1.0]])
M = np.dot(shft, H[0]) # ่ทๅๅทฆ่พนๅพๅๅฐๅณ่พนๅพๅ็ๆๅฝฑๆ ๅฐๅ
ณ็ณป
dst_corners = cv2.warpPerspective(leftgray, M, (w * 2, h)) # ้่งๅๆข๏ผๆฐๅพๅๅฏๅฎน็บณๅฎๆด็ไธคๅน
ๅพ
# cv2.imshow('before add right', dst_corners)
# dst_corners[0:h, 0:w] = leftgray
dst_corners[0:h, w:w + w1] = rightgray # ๅฐ็ฌฌไบๅน
ๅพๆพๅจๅณไพง
# ๅ ้ค็ฉบ็ฝๅ
sum_col = np.sum(np.sum(dst_corners, axis=0), axis=1)
result_img = np.zeros(shape=(dst_corners.shape[0], 1, 3))
for i in range(len(sum_col)):
if sum_col[i] != 0:
result_img = np.hstack([result_img, dst_corners[:, i:i + 1, :]])
result_img = result_img[:, 1:]
# cv2.imshow('dest', dst_corners)
result_name = get_full_view_result_name(filename1, filename2)
cv2.imwrite(dirname + result_name, result_img)
cv2.waitKey()
cv2.destroyAllWindows()
return result_name
public String encode_img_to_base64(String imgurl){
String basepath = "src/main/resources/static/db/";
byte[] data = null;
try{
InputStream in = new FileInputStream(basepath + imgurl);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e){
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
}
public void saveImg(String baseImg, String imgurl){
//ๆญฃๅ่กจ่พพๅผ็็ญ้่งๅ๏ผไธบไบ่ทๅๅพ็็็ฑปๅ
String rgex = "data:image/(.*?);base64";
String type = getSubUtilSimple(baseImg, rgex);
//ๅป้คbase64ๅพ็็ๅ็ผ
baseImg = baseImg.replaceFirst("data:(.+?);base64,", "");
byte[] b;
byte[] bs;
OutputStream os = null;
//ๆๅพ็่ฝฌๆขๆไบ่ฟๅถ
b = Base64.decode(baseImg.replaceAll(" ", "+"));
File imageFile = new File(imgurl);
BASE64Decoder d = new BASE64Decoder();
// ไฟๅญ
try {
bs = d.decodeBuffer(Base64.encode(b));
os = new FileOutputStream(imageFile);
os.write(bs);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.getLocalizedMessage();
}
}
}
}
Thumbnails.of(basepath + imgurl).scale(0.2).toFile(basepath + newimgurl);
ไฝฟ็จMediumTextๅญๆฎต่ฟ่กๅญๅจ
CREATE TABLE `TJ-Memory`.`User` (
`id` INT NOT NULL AUTO_INCREMENT,
`username` VARCHAR(45) NOT NULL,
`password` VARCHAR(45) NOT NULL,
PRIMARY KEY (`id`));
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="site.doublez.tjmemory.dao.PhotoDao">
<insert id = "insert_photo" parameterType="site.doublez.tjmemory.entity.Photo">
INSERT INTO
Photo(ID,USERNAME,PICYEAR,PICMONTH,PICDAY,IMGBASE,DESCRIPTION,PICURL)
VALUES
(#{id},#{username},#{picyear},#{picmonth},#{picday},#{imgbase},#{description},#{picurl});
</insert>
<select id="select_photos_by_year_month" parameterType="site.doublez.tjmemory.entity.DayInfo" resultType="site.doublez.tjmemory.entity.Photo">
SELECT *
FROM Photo
WHERE (USERNAME=#{username} AND PICYEAR=#{picyear} AND PICMONTH=#{picmonth});
</select>
<select id="select_photo_by_date" parameterType="site.doublez.tjmemory.entity.DayInfo" resultType="site.doublez.tjmemory.entity.Photo">
SELECT *
FROM Photo
WHERE (USERNAME=#{username} AND PICYEAR=#{picyear} AND PICMONTH=#{picmonth} AND PICDAY=#{picday});
</select>
</mapper>
้กน็ฎ็ปๆ
-
ๅ็ซฏ
. โโโ HELP.md โโโ README.md โโโ TJ-Memory.iml โโโ mvnw โโโ mvnw.cmd โโโ pom.xml โโโ src โโโ main โ โโโ java โ โ โโโ site โ โ โโโ doublez โ โ โโโ tjmemory โ โ โโโ TjMemoryApplication.java โ โ โโโ controller โ โ โ โโโ CalendarController.java โ โ โ โโโ HistoryController.java โ โ โ โโโ IndexController.java โ โ โ โโโ LoginController.java โ โ โ โโโ MyErrorController.java โ โ โ โโโ PanoramaController.java โ โ โโโ dao โ โ โ โโโ LabelDao.java โ โ โ โโโ PhotoDao.java โ โ โ โโโ UserDao.java โ โ โโโ entity โ โ โ โโโ CalendarInfo.java โ โ โ โโโ CrossConfig.java โ โ โ โโโ DayInfo.java โ โ โ โโโ Label.java โ โ โ โโโ Photo.java โ โ โ โโโ User.java โ โ โโโ service โ โ โโโ LabelService.java โ โ โโโ PhotoService.java โ โ โโโ PythonConnectorService.java โ โ โโโ UserService.java โ โโโ resources โ โโโ application.yml โ โโโ mapper โ โ โโโ LabelMapper.xml โ โ โโโ PhotoMapper.xml โ โ โโโ UserMapper.xml โ โโโ static โ โโโ templates โโโ test โโโ java โโโ site โโโ doublez โโโ tjmemory โโโ TjMemoryApplicationTests.java
-
ๅ็ซฏ
. โโโ static โ โโโ css โ โ โโโ calendar.css โ โ โโโ error.css โ โ โโโ footer.css โ โ โโโ global.css โ โ โโโ hero.css โ โ โโโ history.css โ โ โโโ loader.css โ โ โโโ login.css โ โ โโโ myshare.css โ โ โโโ navigator.css โ โ โโโ panorama.css โ โ โโโ sectioncaption.css โ โ โโโ socialmedia.css โ โ โโโ wavesection.css โ โโโ db โ โโโ fonts โ โ โโโ iconfont.eot โ โ โโโ iconfont.svg โ โ โโโ iconfont.ttf โ โ โโโ iconfont.woff โ โโโ img โ โ โโโ favicon.ico โ โโโ js โ โ โโโ awesome-calendar.js โ โ โโโ calendar.js โ โ โโโ contentful.api.js โ โ โโโ error.js โ โ โโโ hero.js โ โ โโโ history.js โ โ โโโ index.js โ โ โโโ loader.js โ โ โโโ login.js โ โ โโโ myshare.js โ โ โโโ navigator.js โ โ โโโ panorama.js โ โ โโโ socialmedia.js โ โ โโโ util.js โ โ โโโ waterripple.js โ โ โโโ wavesection.js โ โโโ json โ โ โโโ navigator.json โ โ โโโ socialmedia.json โ โ โโโ testcalendar.json โ โ โโโ tongji.json โ โโโ lib โ โ โโโ share.min.css โ โ โโโ social-share.min.js โ โ โโโ three.js โ โ โโโ tpanorama.js โ โ โโโ vue.min.js โ โโโ python โ โโโ panorama.py โ โโโ test.py โโโ templates โโโ calendar.html โโโ error.html โโโ index.html โโโ login.html โโโ panorama.html