diff --git a/assets/img/map.png b/assets/img/map.png new file mode 100644 index 0000000..d8f879c Binary files /dev/null and b/assets/img/map.png differ diff --git a/assets/img/night.jpg b/assets/img/night.jpg new file mode 100644 index 0000000..3e5e831 Binary files /dev/null and b/assets/img/night.jpg differ diff --git a/assets/img/sunrise.jpg b/assets/img/sunrise.jpg new file mode 100644 index 0000000..2949e7b Binary files /dev/null and b/assets/img/sunrise.jpg differ diff --git a/src/Main.elm b/src/Main.elm index 9d25004..4ca1613 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -486,6 +486,7 @@ sitemap = Dict.fromList (itemize ([ "/", "/index.html" ] ++ getPaths "src" ++ getPaths "index" ++ getPaths "home") pageHome ++ itemize (getPaths "entries") pageEntries + ++ itemize (getPaths "about") pageAbout ) @@ -724,6 +725,163 @@ pageHome model = ] +pageAbout : Model -> List (Html Msg) +pageAbout model = + [ Element.layout + [ width fill + ] + (column [ width fill ] + [ column + [ width fill + , height fill + , spacing (vh2pt model -100) + , id "zero" + ] + [ el + [ width fill + , height (vh2px model 100) + , Background.color black + ] + Element.none + , animatedEl crossfadeIn + [ width fill + , height (vh2px model 100) + , Background.gradient { angle = 45, steps = [ rgb255 255 0 140, rgb255 40 0 255 ] } + ] + Element.none + , animatedEl crossfadeOut + [ width fill + , height (vh2px model 100) + , Background.gradient { angle = 0, steps = [ rgb255 0 140 255, rgb255 0 150 25 ] } + ] + Element.none + , el + ([ alignLeft + , alignTop + , width (vw2px model 50) + , height (vh2px model 100) + , paddingEach + { top = vh2pt model 20 - 96 + , bottom = 0 + , left = vw2pt model 10 + , right = 0 + } + ] + ++ heading + ) + (column + [ spacing 35 + ] + [ menu model + , text "Access" + , column [ spacing 15 ] + [ row + [ spacing 15 ] + [ linkBtnInt "← Back" "/" + , btn "Directions" (Scroll "one") + ] + , row [ spacing 15 ] + [ btn "Facilities" (Scroll "two") + , btn "Web Accessibility" (Scroll "three") + ] + ] + ] + ) + , el + [ alignRight + , alignTop + , width (vw2px model 60) + , height (vh2px model 100) + , paddingEach + { top = vh2pt model 25 + , bottom = vh2pt model 25 + , left = 0 + , right = 0 + } + ] + (view3DWalk model) + ] + , column + (page model ++ [ id "one" ]) + [ image (fullImage model) + { src = "../assets/img/map.png" + , description = "mit campus map with pin at macgregor house" + } + , column (pageText model) + [ row [ spacing 10 ] + [ btn "↑" (Scroll "zero") + , btn "↓" (Scroll "two") + ] + , paragraph + subheading + [ text "Directions" ] + , paragraph bodyText + [ text "MacGregor's address is " + , paragraph [ Font.bold ] [ text "450 Memorial Drive, Cambridge, MA 02139" ] + , text ". It is building number " + , paragraph [ Font.bold ] [ text "W61" ] + , text " on the " + , inlineLink "MIT campus" "https://whereis.mit.edu/?go=W61" + , text ". See the " + , inlineLink "OpenStreetMaps identifier" "https://www.openstreetmap.org/way/1246607679" + , text " for directions and more information. If you are mailing a package to a MacGregor resident, follow the directions listed on the " + , inlineLink "MIT DSL site" "https://studentlife.mit.edu/housing/undergraduate-housing/mailing-shipping-information" + , text "." + ] + ] + ] + , column + (page model ++ [ id "two" ]) + [ image (fullImage model) + { src = "../assets/img/night.jpg" + , description = "looking out into the starry night from the second floor patio" + } + , column (pageText model) + [ row [ spacing 10 ] + [ btn "↑" (Scroll "one") + , btn "↓" (Scroll "three") + ] + , paragraph subheading [ text "Facilities and Information" ] + , paragraph bodyText + [ text "MacGregor's main facilities are all located on the ground floor. They include a central courtyard, conference/seminar room, music practice room, two laundry rooms, gym, ice machine, game room with a black and white and color printer and an Athena computing cluster, and dining room with a dance studio. All of these facilities are available to residents at any time except when they are being used for " + , inlineLink "events" "https://calendar.google.com/calendar/embed?src=c_c9fb13003264d5becb74cf9ba42a087d8a4a180d927441994458a07ac146eb88%40group.calendar.google.com&ctz=America%2FNew_York" + , text "." + ] + , paragraph bodyText + [ text "You can ask the front desk for a key to access the music practice room. Printers in MacGregor can be located " + , inlineLink "here" "https://print.mit.edu" + , text " (search for W61). Laundry uses the " + , inlineLink "CSCGo app" "https://mycscgo.com/laundry" + , text " for payments (approximately $1.25 for a single wash or dry cycle). You can learn more about MacGregor " + , inlineLink "here" "https://mitguidetoresidences.mit.edu/residences/macgregor-house" + , text "." + ] + ] + ] + , column + (page model ++ [ id "three" ]) + [ image (fullImage model) + { src = "../assets/img/sunrise.jpg" + , description = "sunrise over back bay, boston, as seen from macgregor south side entrance" + } + , column (pageText model) + [ row [ spacing 10 ] + [ btn "↑" (Scroll "two") + , btn "Top" (Scroll "zero") + ] + , paragraph subheading [ text "Accessibility is our highest priority." ] + , paragraph bodyText + [ text "If you're experiencing issues viewing or interacting with parts of this website, please do not hesitate to " + , inlineLink "contact the webmaster" "mailto:ananthv@mit.edu" + , text " at any time. We strive to make the story of MacGregor widely accessible to the general public, and we value your input and community support in achieving that goal." + ] + ] + ] + ] + ) + ] + + pageEntries : Model -> List (Html Msg) pageEntries model = [ Element.layout @@ -1092,7 +1250,7 @@ pageEntries model = [ column (pageText model) [ row [ spacing 10 ] [ btn "↑" (ScrollToEntry "G") - , btn "TOP" (ScrollToEntry "zero") + , btn "Top" (ScrollToEntry "zero") ] , paragraph subheading @@ -1540,6 +1698,78 @@ view3DTower model = ) +view3DWalk : Model -> Element msg +view3DWalk model = + Element.html + (let + entity : Entity Obj.Decode.ObjCoordinates + entity = + case model.mesh of + Nothing -> + Scene3d.mesh (Material.matte (Color.rgb255 173 111 101)) pyramidMesh + + Just mesh -> + case model.textures of + Nothing -> + Scene3d.mesh (Material.matte (Color.rgb255 173 111 101)) (Mesh.texturedFacets mesh) + + Just textures -> + Scene3d.mesh textures (Mesh.texturedFacets mesh) + + camera : Camera3d.Camera3d Length.Meters coordinates + camera = + let + phi : Float + phi = + 180 * frac (model.angle / 180) + + winding : Float + winding = + 360 * frac (model.angle / 360) + + direction : Float + direction = + abs (180 - winding) / (180 - winding) + + interp : Float -> Float -> Angle.Angle + interp a b = + Angle.degrees + (if direction > 0 then + a + (b - a) * phi / 180 + + else + b + (a - b) * phi / 180 + ) + in + Camera3d.perspective + { viewpoint = + Viewpoint3d.lookAt + { focalPoint = Point3d.origin + , eyePoint = + let + theta : Angle.Angle + theta = + interp -90 90 + in + Point3d.meters (model.radius * Angle.cos theta) model.elevation (model.radius * Angle.sin theta) + , upDirection = Direction3d.xy (interp (90 + 45) (90 - 45)) + } + , verticalFieldOfView = Angle.degrees 60 + } + in + Scene3d.sunny + { entities = [ entity ] + , camera = camera + , upDirection = Direction3d.z + , sunlightDirection = Direction3d.yz (Angle.degrees -120) + , background = Scene3d.transparentBackground + , clipDepth = Length.centimeters 1 + , shadows = False + , dimensions = ( Pixels.int (round (vw model 60)), Pixels.int (round (vh model 100)) ) + } + ) + + crossfadeIn : Animation crossfadeIn = Animation.fromTo